In-Person Payments API Reference
Introduction
This page provides an API Reference for using the Cashflows terminals powered by Kinetic.
The Kinetic solution is a full, standalone payment application for PCI-PTS secure payment devices. We have extended this with the Kinetic Connect API to:
Make it easy to add secure card acceptance to any system. iOS, Android (including other apps in an Android environment), PC, web frameworks, local and remote tablet OS - just about any modern technology capable of implementing connection via a REST API
Keep the complexity of payment processes and the seriousness of card data security away from any other system
Accommodate workflow, branding and low impact UI changes gracefully, fast and without impacting payment and security certifications
Before you begin
The Kinetic solution is a full payment acceptance application. It can work on its own without needing a phone, tablet or PC to start a transaction. It works best as an add-on to other applications and systems though, and to initiate a transaction from another device you simply issue a REST (JSON over HTTPS) command via Wi-Fi, Ethernet connected networks and inter-app in Android environments.
The Kinetic solution interfaces directly to the payment processor’s acquiring platform. There is no gateway or other system in the middle. All transaction reporting, chargebacks and other financial capabilities are available through the payment provider dashboards and tools.
The Kinetic solution is designed for general retail, quick serve restaurant, fine dining restaurant across small, medium and enterprise markets.
No special tools are needed to interface with the Kinetic Connect API and there are no additional proprietary libraries to add to your project. The Kinetic devices re web addressable on the network to which they are connected, including the local loop address (127.0.0.1). The devices are then interacted with via the REST API using JSON over HTTP.
Kinetic Go 2 REST API
Kinetic Go contains an embedded REST API served over HTTP. This API is used to initiate, monitor and Ex: GET http://127.0.0.1/api/v2/device.json
The following settings control the operation of the webserver:
webserver.http.enabled
- Whether to serve the REST API over HTTP. Default value:true
webserver.http.port
- What port number to run the HTTP server on. Default value:8080
API Endpoints
The original Kinetic Go software included a REST API, and this was deemed version 1 of the REST API.
In Kinetic Go 2, a rewritten REST API has been included, so this is deemed version 2 of the REST API. Therefore, API endpoints are prefixed with /api/v2/
.
GET /api/v2/device.json
- Returns information about the underlying hardware. This is an authorized endpoint.
Response Body:
{
"success": true,
"device": {
"manufacturer": "Device manufacturer name",
"family": "Device hardware family",
"serial_number": "Device serial number"
}
}
GET /api/v2/ping.json
- Simple “ping” which returns a static response. Useful for checking that the software is functioning properly.
Response Body:
{
"success": true,
"ping": true
}
GET /api/v2/settings.json
- Returns a JSON document describing the device’s internal settings. This is an authorized endpoint.
Response Body:
{
"success": true,
"settings": {
// Name of the primary host module to use
"host": {
"module": "dummy"
},
// Host module settings
"dummy": {
"address": "123.123.123.123",
"port": 23215,
"terminal_id": "12345678",
"merchant_id": "87654321",
"deferred_auth": {
"enabled": false
},
// Receipt header and footer information for this host module
"receipt": {
"footer": {
"line1": "",
"line2": "",
"line3": "",
"line4": "",
"line5": ""
},
"header": {
"line1": "",
"line2": "",
"line3": "",
"line4": "",
"line5": ""
},
},
// ...
},
// Default receipt header and footer information (if not overridden
// by host module)
"receipt": {
"footer": {
// ...
},
"header": {
// ...
},
},
// ...
}
}
GET /api/v2/transactions.json
- Returns a list of the transactions in the device’s transaction database. The objects in the response contain some of the most common transaction fields. This is an authorized endpoint.
Response Body:
{
"id": "transaction id",
"started_at": 1,
"ended_at": 1,
"result": "approved|declined|cancelled|error",
"amount": 100,
"host": "dummy",
"type": "sale|refund|reversal|reconciliation",
"account_number": "4***********1111",
"is_reversed": false
}
GET /api/v2/transactions/[id].json
- Returns a document describing the transaction with the specified ID. This is an authorized endpoint.
GET /api/v2/transactions/(latest|last).json
- Returns a document describing the most recent transaction in the transactions database. This is an authorized endpoint.
GET /api/v2/transactions/current.json
- Returns a document describing the currently in progress transaction in the transactions database. If no transaction is in progress, an error result and error status code are returned. This is an authorized endpoint.
POST /api/v2/transactions/[type].json
- Begins a new transaction of the specified type. Returns a document describing the new transaction. This is an authorized endpoint. Types include: sale|refund|reversal|reconciliation
Response Body for the above 4 requests:
{
"success": true,
"transaction": {
// Masked PAN, e.g. "4***********1111"
"account_number": "string",
// Transaction amount
"amount": "number",
// Cashback amount
"amount_other": "number",
"app_confirmation_required": "boolean",
"app_label": "string",
// The different types of input attempted for this transaction "attempted_sources": [
"contactless", "contact_emv", "keypad",
"mag_stripe"
],
// The number of attempts remaining until fallback or the transaction is
// cancelled
"attempts_remaining": "number,"
"auth_code": "string",
// Card details, such as track data.
"card_details": {
"scheme": "visa-old-us | visa-wave-2 | visa-qvsdc | visa-msd |
paypass-magstripe | paypass-mchip | jcb-wave-2 |
jcb-qvsdc | amex-emv | amex-magstripe | discover-zip |
jcb-emv | jcb-msd | jcb-legacy | discover-dpas |
interac-flash | meps-mccs | cup-qpboc | discover-magstripe |
unknown (%x)",
"track2": "Masked track 2 data, string"
},
"card_expiry": "YYMM",
"cvm_mode": "offline_pin|online_pin|signature|offline_pin",
// Transaction duration in seconds
"duration": "number",
// Transaction end timestamp (seconds since the UNIX epoch, 00:00:00 Jan 1 1971)
"ended_at": "number",
// CVM result. Could be "ok", "failed", "blocked", or an array
// containing both "failed" and "blocked". Could also be a hexadecimal
// value according to the contactless EMV specification.
"cvm_result": "string | array",
// The name of the host module against which this transaction was run. "host": string,
// Unique identifier for this transaction. Typically a UUID, but can be
// any value generated by the client application. If omitted, a UUID is
// generated.
"id": "string",
// The most recently attempted input peripheral used to provide card
// data. For a completed transaction, this is the authoritative source
// of the card data. For a transaction still in progress, this field
// could change, for example in the event of corrupted or invalid data.
"input_source": "contactless | contact_emv | keypad | mag_stripe",
// True if this transaction is still in progress.
"is_active": "boolean",
// True if this transaction is a contactless transaction.
"is_contactless": "boolean",
// True if this transaction exceeded the contactless transaction limit.
"is_contactless_transaction_limit_exceeded": "boolean",
// True if this transaction is a deferred authorization. That is, it
// could not be approved online, and the merchant decided to approve it
// (and assume the risk).
"is_deferred_auth": "boolean",
// True if this is an EMV transaction.
"is_emv": "boolean",
// True if this is a fallback transaction. That is, an attempted
// contactless or contact EMV transaction failed, and the user was
// prompted to insert or swipe their card instead.
"is_fallback": "boolean",
// True if this transaction was forced online, even if it might have
// been approved offline.
"is_force_online": "boolean",
// True if the card data for this transaction was manually keyed.
"is_keyed": "boolean",
// True if this transaction went online for an approval.
"is_online": "boolean",
// True if this transaction prompted the user to enter their PIN, and if
// the PIN was encrypted to be sent to the host for validation.
"is_online_pin": "boolean",
// True if this transaction prompted the user to enter their PIN, and if
// the PIN was validated by the card, without being sent to the host.
"is_offline_pin": "boolean",
// True if this transaction has been reversed/voided.
"is_reversed": "boolean",
// True if this is an SCA "single-tap" transaction. That is, a
// transaction which, having gone online for an approval, was rejected
// by the host with instructions to the user to enter their PIN for
// online PIN validation. It is called "single-tap" because the card
// details are retained, and therefore the user does not have to present
// their card a second time.
"is_sca_single_tap": "boolean",
// True if this transaction requires a signature.
"is_signature_required": "boolean",
// Host-specific proprietary "issuer ID" field. This field can be used
// to identify the card issuer (VISA, Mastercard, etc), but the values
// depend on the host, and not all host modules will populate this
// field.
"issuer_id": "string",
// The KSN for an encrypted online PIN block or other encrypted card
// data. May be `null` if not used for this transaction.
"ksn": "string",
// The number of seconds since the Unix epoch since the most recent
// attempt to approve this transaction, or `null` if this is not a
// deferred authorization.
"last_deferred_auth_attempted_at": "number",
// The message number of this transaction.
"message_number": "number",
// The number of attempts to gather card data for this transaction.
"num_attempts": "number",
// The number of attempts that have been made to approve this
// transaction if it is a deferred authorization, or `null` if it is
// not.
"num_deferred_auth_attempts": "number",
// Online request information that was or will be sent to the host. The
// format of this data depends on the host.
"online_request": { /* host-dependent data */ },
// Online response information that was returned by the host. The format
// of this data depends on the host.
"online_response": { /* host-dependent data */ },
// The result that was parsed out of the online request information.
// This field provides a common way to access the host response, so that
// the exact format of the `online_request` field does not need to be
// known.
"online_result": "approved|declined|cancelled|error",
// The encrypted PIN block for online PIN transactions, or `null`.
"pin_block": "string",
// The reference number for this transaction. The exact format of this
// field varies by host, and is populated by the host module.
"reference_number": "string",
// For reversal/void transactions, this field represents the unique ID
// of the transaction that is being reversed.
"reference_txn_id": "string",
// The final decision as to whether this transaction was approved or
// declined. May differ from `online_result`, in that a transaction can
// be approved by the host and then declined by the card, or (in rare
// instances) declined by the host and then approved by the card.
"result": "approved|declined|cancelled|error",
// Data that represents what operations can and can’t be performed with
// the given card. Mostly relevant for magnetic stripe (swipe)
// transactions. "services": {
// The un-parsed service code for this transaction.
"code": "string",
// The final decision as to whether this transaction was approved or
// declined. May differ from `online_result`, in that a transaction can
// be approved by the host and then declined by the card, or (in rare
// instances) declined by the host and then approved by the card.
"result": "approved|declined|cancelled|error",
// Data that represents what operations can and can’t be performed with
// the given card. Mostly relevant for magnetic stripe (swipe)
// transactions.
"services": {
// The un-parsed service code for this transaction.
"code": "string",
// The interchange rules, parsed from the service code.
"interchange_rules": "interchange_ok|interchange_prefer_ic|
natl_interchange_only|natl_interchange_only_prefer_ic|
no_interchange|test|unknown",
// The authorization processing rules, parsed from the service code.
"authorization_processing_rules": "normal|contact_issuer_online|contact_issuer_online_except_under_agreement|unknown",
// The range of allowed services, parsed from the service code.
"range_of_services": "no_restrictions_pin_required|no_restrictions|no_cash|atm_only_pin_required|cash_only|no_cash_pin_required|no_restrictions_prefer_pin|no_cash_prefer_pin|unknown",
},
// The session/batch number for this transaction.
"session_number": "number",
// Whether this the transaction logic has indicated that this
// transaction should enter fallback mode. This is normally used for
// transactions that have not yet completed processing, but can be
// useful for debugging purposes, even for transactions that have
// completed.
"should_fallback": "boolean",
// Whether this the transaction logic has indicated that this
// transaction should be retried. This is normally used for
// transactions that have not yet completed processing, but can be
// useful for debugging purposes, even for transactions that have
// completed.
"should_retry": "boolean",
// A monotonically incrementing number used to sequentially identify
// this transaction.
"stan": "number",
// The time that this transaction was started, represented as the number
// of seconds since the UNIX epoch.
"started_at": "number",
// The current high-level status of this transaction.
"status": "string",
// A more detailed, lower-level status of this transaction.
"status_details": "string",
// The set of EMV tags retrieved primarily from the card. Some tags may
// be added as the transaction progresses. Only applies to contact or
// contactless EMV transactions. The tag name and value are hexadecimal
// strings such as `"01234567890ABCDEF"`.
"tags": {
"EMV tag name": "EMV tag value",
// ...
},
// The terminal’s preference as to whether this transaction should go
// online for approval, or be approved or declined offline without
// interaction with the host. This field may change during the course
// of a transaction, and is not authoritative (i.e. the terminal’s
// preference is considered but is not a final decision).
"terminal_online_decision": "approved|declined|go_online|unknown",
// The number of milliseconds which will be allowed for the user to
// prevent their card information after which the transaction will be
// cancelled. Defaults to 150,000 (2 minutes 30 seconds).
"timeout_ms": "number",
// The amount of this transaction which is a tip rather than part of the
// base transaction amount.
"tip_amount": "number",
// The total amount to be authorized for this transaction, which should
// equal `amount + tip_amount + amount_other`.
"total_amount": "number",
// The transaction type. Note that `"reversal"` and `"void"` are
// essentially the same thing, and `"technical_reversal"` is merely a
// system-generated reversal (e.g. due to a network communications // error).
"type": "sale|refund|reconciliation|technical_reversal|reversal|void"
}
}
GET /api/v2/screens/current.json
– Returns a document describing the current screen state of the device. This is an authorized endpoint. This is used in conjunction with the response to transactions/current.json | transactions/latest.json to derive the transaction status, where “app.views.layouts.idle” shows that the transaction event is completed, and the device is ready for another transaction.
Response Body:
{
"scene": {
"path": "app.views.layouts.idle",
"text": "Tap Green To Start\nDevice Name\n\n\n\n"
},
"success": true
}
Printer and Receipt APIs
It is possible to print arbitrary messages to the device’s printer, if available. It is also possible to request correctly formatted (and certified) receipt messages for each transaction. The output of the latter is compatible with the former, so you can request a receipt and send it directly to the printer without having to manipulate the result.
Printer
There is one API available for printing. It takes as input a JSON array containing a series of objects which describe discrete instructions to be sent to the printer. For example, the array could contain the equivalent of “scroll down”, “print a header in bold”, “print some text in italics”, and “scroll down again”. These instructions will be processed sequentially, compiled into a command buffer, and dispatched to the printer.
POST /api/v2/print.json
- Sends data to the printer to be printed. If this device does not have a printer, a 400 Bad Request may be generated. Other errors may be generated, for example if the printer is out of paper.
Request Body:
{
"instructions": [
/* array of printer instructions; see below */
]
}
Response Body:
{
"success": true
}
Printer Instructions
There are currently 3 types of instructions: scroll, text and flush. Others (such as image) are planned to be added in the future.
text
- This command can be used to print text in a variety of formats. It takes the form:
{
"command": "text",
"text": "Hello, world!",
"x": 100,
"y": 100,
"font_size": 24,
"line_width": 10, // optional; default 10
"skew_x": 0, // optional; default 0
"underline": false, // optional; default false
"strikethru": false, // optional; default false
"reverse": false, // optional; default false
"family": "Arial" // optional; default "Arial"
}
Intuitively, the text property specifies the text to be printed, and the x
property represents the horizontal distance from the left to draw the text.
The y
property may require more explanation. It represents a vertical distance into the buffer to place the text prior to printing, with 0 at the current print head position and positive values being further down on the page, measured in dots (the printing equivalent of a pixel). Negative values are not allowed. When commands are processed, a memory buffer, which is really just a glorified bitmap image, is first allocated and then drawing operations are applied to it. When the buffer has been completely prepared, it is dispatched to the printer all at once. Therefore, the y
property represents the vertical distance from the current position of the print head to place the text, with 0 at the top (the current position). Higher values of y will place the text further toward the bottom of the buffer and therefore lower on the printed page, so commands with a lower y
value will be printed first, even if they appear later in the instruction set.
Buffer management happens entirely behind-the-scenes. First the commands are analyzed to determine the required buffer size, and then they are processed to populate the buffer. Finally, the buffer is dispatched and printing begins.
Thus, if you have a great deal of printer output, consider breaking it into several batches separated by a flush command. This will generate multiple buffers, allowing the printer to operate in batches, instead of first populating one very large buffer. You may find better performance and less memory pressure using this strategy.
flush
- The flush command is used to flush the print buffer between commands. You usually shouldn’t need it because flushes are generated automatically, but if your print result is laid out improperly or if performance is poor due to a very large amount of text, try adding a flush command at strategic intervals.
The form of a flush command is:
{
"command": "flush"
}
scroll
- This is a very simple command that merely scrolls the page, creating a region of white space. It takes the form {"command":"scroll","amount":100}
, where amount represents the distance to be scrolled, in dots.
Note
The scroll command does not make use of the offscreen print buffer. If a scroll command is encountered, the buffer will be immediately flushed, causing the printer to begin printing, and then the scroll command will be applied. Therefore, after calling scroll, if you have more printing to do, reset your y values back to 0 to accommodate the fact that you will be printing into a new buffer.
Receipts
GET /api/v2/transactions/[id]/receipts/merchant.json
- Returns a JSON array of receipt-printing instructions. The output of this API is compatible with the POST /api/v2/print.json API.
The merchant copy of a receipt is intended to be kept by the merchant for their records. In the case of a reconciliation transaction, the only receipt that is generated is always a merchant copy. For all other transactions, a merchant and cardholder (customer) copy are generated. Therefore, under normal circumstances, this API should always succeed.
Response Body:
{
"success": true,
"receipt": [
// Each array element is an instruction compatible with the printer API.
// It can also be parsed to reconstruct the receipt digitally, if
// desired.
{
"command": "scroll",
"amount": 100
},
{
"command": "text",
"text": "Hello, world!",
"x": 32,
"y": 32,
"font_size": 12
},
// ...
]
}
GET /api/v2/transactions/[id]/receipts/cardholder.json
- Returns a JSON array of receipt-printing instructions. The output of this API is compatible with the POST /api/v2/print.json API.
The cardholder copy of a receipt is intended to be kept by the cardholder (customer) for their records. Whether to print it is often optional. In the case of a reconciliation transaction, the only receipt that is generated is always a merchant copy. Therefore, this API will fail with 400 Bad Request if a cardholder receipt is requested for a reconciliation transaction.
Response Body:
{
"success": true,
"receipt": [
// Each array element is an instruction compatible with the printer API.
// It can also be parsed to reconstruct the receipt digitally, if
// desired.
{
"command": "scroll",
"amount": "100"
},
{
"command": "text",
"text": "Hello, world!",
"x": 32,
"y": 32,
"font_size": 12
},
// ...
]
}
GET /api/v2/transactions/[id]/receipts/reconciliation.json
- Returns a JSON array of receipt-printing instructions. The output of this API is compatible with the POST /api/v2/print.json API.
The reconciliation receipt is the result of end-of-day operations and is intended for the merchant to keep for their records, and for informational purposes. For reconciliation transactions, this API is an alias of /api/v2/transactions/[id]/receipts/merchant.json. The output is identical. However, unlike merchant.json, if the requested transaction is not a reconciliation, this API will fail with 400 Bad Request. Therefore, it may be useful as a sanity check to ensure the requested transaction is actually a reconciliation. If you prefer simpler, but less robust logic and are confident that the transaction ID is correct, use merchant.json for the same result.
Response Body:
{
"success": true,
"receipt": [
// Each array element is an instruction compatible with the printer API.
// It can also be parsed to reconstruct the receipt digitally, if
// desired.
{
"command": "scroll",
"mount": 100
},
{
"command": "text",
"text": "Hello, world!",
"x": 32,
"y": 32,
"font_size": 12
},
// ...
]
}