Pinpad Interface API
Document Version 1.0 | Last updated: Wednesday, 25 July, 2018
Strictly Confidential
The Afterpay Touch Pinpad Interface API can be used by a Practice Management Systems (PMS) to request for payments using in store terminals.
The document has language examples in curl. You can view code examples in the dark area to the right.
Copyright © Afterpay Touch
API Endpoint
Production Environment
https://healtchclaims.touchcorp.com/
Integration Environment
https://healtchclaims-3pi.touchcorp.com/
Certification Environment
https://healtchclaims-stg.touchcorp.com/
REST
The Afterpay Touch Private Health API is organized around REST. The API attempts to use predictable, resource-oriented URLs and to use HTTP response codes to indicate errors.
The API will occasionally deviate from REST principles to reduce chattiness so that latency is minimised.
HTTPS
The Afterpay Touch Health API requires all communications to be secured using TLS 1.2 or greater.
Request and Response Headers
Clients must send appropriate headers with all requests.:
Authorization: Bearer {accessToken}
Accept: application/json
POST and PUT requests must include one additional header:
Content-Type: application/json
All GET requests return JSON and thus must set compatible accept headers, either application/json or */*.
All endpoint responses provide data as JSON in the response body and include the header:
Content-Type: application/json
Activation
Will use Aftepay Touch standard activation process. Device activation relies on a valid TLS certification managed by Afterpay Touch (APT) host. The device can then be activated using the Integrated Health Activation API.
Authentication
To authorize, use this code:
# With shell, you can just pass the correct header with each request
curl "https://{{Environment}}/v1/ping" \
-H "Authorization: Bearer <accessToken>"
Make sure to replace
accessTokenwith a valid access token.
Afterpay Touch Health uses access tokens to allow access to the API. Access tokens are created using the Create Token endpoint.
Afterpay Touch Health expects the access token to be included in all API requests as a HTTP header such as the following:
Authorization: Bearer <accessToken>
Service Status
Ping
Example Ping Request
curl "https://{{Environment}}/ping"
Response (200)
This endpoint can be used to check that the service is reachable and available.
HTTP Request
Get https://{{Environment}}/ping
Device Authentication
Device Activation
Example Device Activation Request
curl "https://{{Environment}}/v1.1/devices/activate" \
-X POST \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
"secret":"xyzabc",
"attributes": "pmsVersion=1.0, pmsVendor=Touch, pmsProduct=TestHarness"
}'
Returns response headers like so:
HTTP/1.1 200 Created
Content-Type: application/json
Date: Mon, 11 Dec 2017 15:17:53 GMT
Connection: keep-alive
The above command returns JSON structured like so:
{
"deviceId":"1234",
"deviceKey":"bb68452ad2d743db75a270bf2c305df9abeefcb3e02084fc1ff7a3ba61ed46d5"
}
This endpoint performs a one time activation of a device, providing a device’s identification and authorization credentials. Multiple calls to the activation endpoint will result in the creation of a new credentials (deviceKey), maintaining the deviceID. The device credentials obtained from the activation request should be securely stored on the device. The device credentials are required to create access tokens used for authentication.
HTTP Request
POST https://{{Environment}}/v1.1/devices/activate
HTTP Headers
| Parameter | Description |
|---|---|
| Content-Type | application/json |
| Accept | application/json |
Arguments
| Parameter | Type | Description |
|---|---|---|
| secret | required string |
The device secret provided for activation. |
| attributes | optional |
A free text field that can be populated with device or PMS Vendor specific information. Suggest comma separated list of key/value pairs. |
Response
Returns the devices authorization credentials
| Parameter | Description |
|---|---|
| deviceId | A device ID require for auditing and authentication. |
| deviceKey | A secret key required for authentication. |
Errors
Can return the following specific error responses
| Status Code | Type | Description |
|---|---|---|
| 401 | unathorized | will be retruned if the secret is not found or is invalid |
| 412 | Precondition Failed | will be returned if the secret length does not meet the valid parameter i.e. between 10 and 32 |
Connection timeouts
| Timeout | Time (seconds) |
|---|---|
| Open | 10 |
| Read | 20 |
Create Token
Example Create Token Request
curl "https://{{Environment}}/v1/devices/token" \
-X POST \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
"deviceId":"hj65f52a",
"deviceKey":"bb68452ad2d743db75a270bf2c305df9abeefcb3e02084fc1ff7a3ba61ed46d5"
}'
Returns response headers like so:
HTTP/1.1 200 Created
Content-Type: application/json
Date: Mon, 11 Dec 2017 14 15:17:53 GMT
Connection: keep-alive
The above command returns JSON structured like so:
{
"accessToken":"86bc8b2b973d5046d82432862254dfb5967a6db7c844bf615ab8eba17082105b",
"expiresInSecs":14400
}
This endpoint creates a device access token. The device will need to periodically renew the access token, indicated by expiresInSecs, required by all API endpoints.
HTTP Request
POST https://{{Environment}}/v1/devices/token
HTTP Headers
| Parameter | Description |
|---|---|
| Content-Type | application/json |
| Accept | application/json |
Arguments
| Parameter | Description |
|---|---|
| deviceId | The device ID obtained during activation |
| deviceKey | The device secret key obtained during activation |
Response
Returns the devices access token
| Parameter | Description |
|---|---|
| accessToken | An access token. |
| expiresInSecs | The access token’s expiry time in second. |
Errors
Can return the following specific error responses
| Status Code | Type | Description |
|---|---|---|
| 401 | unathorized | Will be returned if the secret is invalid. |
Connection timeouts
| Timeout | Time (seconds) |
|---|---|
| Open | 10 |
| Read | 20 |
Access Token Validation Ping
Example API key validation via HEAD request
curl "https://{{Environment}}/v1/ping" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H "Authorization: Bearer <accessToken>" \
If the key is VALID, you will receive a HTTP 200 response
HTTP/1.1 200 OK
Content-Type: application/json
Date: Mon, 11 Dec 2017 15:17:53 GMT
Connection: keep-alive
If the key is INVALID, you will receive a HTTP 401 response
HTTP/1.1 401 Unauthorized
Cache-Control: must-revalidate,no-cache,no-store
Content-length: 1327
Content-Type: text/html;charset=ISO-8859-1
Date: Mon, 11 Dec 2017 15:15:11 GMT
Connection: keep-alive
If you wish to validate your access token, you can make an authenticated HEAD request to the /v1/ping endpoint.
HTTP Request
Get https://{{Environment}}/v1/ping
HTTP Headers
| Parameter | Description |
|---|---|
| Content-Type | application/json |
| Accept | application/json |
| Authorization | Bearer |
Response
Returns the key valid response (200)
Errors
Can return the following specific error responses
| Status Code | Type | Description |
|---|---|---|
| 401 | unathorized | will be retruned if the secret is not found or is invalid |
Models
CardDataInfo Object
Example CardDataInfo Object
{
"cardType": "VISA",
"cardName": "04",
"track2": "4940520000006692=1810???????????????????"
}
| Parameter | type | Description |
|---|---|---|
| cardType | String | |
| cardName | String | |
| track2 | String | |
| Source | String | |
| track1 | String | |
| track3 | String | |
| selectedAccount | String | “Savings” “Cheque” “Credit” |
EventInfo Object
Example EventInfo Object
{
"displayText": ["INITIALISING ", "PLEASE WAIT "],
"okKeyFlag": false,
"cancelKeyFlag": false,
"yesKeyFlag": false,
"noKeyFlag": false,
"authoriseKeyFlag": false,
"receiptType": "Logon"
}
| Parameter | type | Description |
|---|---|---|
| displayText | Array | An array of string to display (one line per index) |
| okKeyFlag | Boolean | OK Key present |
| cancelKeyFlag | Boolean | Cancel Key present |
| yesKeyFlag | Boolean | Yes Key present |
| noKeyFlag | Boolean | No Key present |
| authoriseKeyFlag | Boolean | Authorise Key present |
| inputDataFieldKeyFlag | String | Present if “authoriseKeyFlag” = true Values are: “Normal” = normal ASCII entry “Amount” = formatted amount entry ($0.cc) “NoDollarAmount” = amount with no dollar sign “Password” = masked password entry “Supervisor” = supervisor request entry “OneKey” = one key entry |
| receiptType | String | “Customer” “Merchant” “Settlement” “Logon” “Audit” “Duplicate” “Unknown” |
Merchant Object
Example Merchant Object
{
"id": "00019017001",
"name": "DOCTOR ONE"
}
| Parameter | type | Description |
|---|---|---|
| id | String | Merchant ID |
| name | String | Merchant Name |
PinPadInfo Object
Example PinPadInfo Object
{
"terminalId": "00019017001",
"dateTime": "2018-01-29T13:42:44.000+11:00",
"stan": 6210,
"aiic": "560254",
"serialNumber": "0000000075201724",
"versionNumber": "000842",
"timeout": 45,
"loggedOnFlag": false,
"eftposNetwork": "ANZPC-EFTPOS"
}
| Parameter | type | Description |
|---|---|---|
| merchant | String | |
| merchantId | String | |
| terminalId | String | |
| datetinme | String | ISO 8601 UTC format |
| stan | String | |
| aiic | String | |
| nii | String | |
| serialNumber | String | |
| versionNumber | String | |
| timeout | String | |
| loggedOnFlag | String | |
| eftposNetwork | String |
ReceiptPrintingInfo Object
Example ReceiptPrintingInfo Object
{
"printerType": "pinpad",
"cutReceipt": true
}
| Parameter | type | Description |
|---|---|---|
| printerType | String | “POS” = POS printer “Windows” = Windows printer “PinPad” = PINpad printer |
| cutReceipt | Boolean |
ResponseInfo Object
Example ResponseInfo Object
{
"successFlag": true,
"responseCode": "00",
"responseText": "APPROVED "
}
| Parameter | type | Description |
|---|---|---|
| successFlag | Boolean | |
| responseCode | String | |
| responseText | String |
TransactionInfo Object
Example TransactionInfo Object
{
"transactionType": "Purchase",
"accountType": "Credit ",
"purchaseAmount": 1.00,
"cashAmount": 0.00,
"tipAmount": 0.00,
"authorisationNumber": "095250",
"referenceNumber": "1517195358087",
"rrn": "000000000045",
"dateTime": "2018-01-29T14:09:32.000+11:00",
"settlementDate": "2901"
}
| Parameter | type | Description |
|---|---|---|
| transactionType | String | “Purchase” “Refund” |
| currencyCode | String | |
| accountType | String | |
| purchaseAmount | Number | 0.cc format |
| cashAmount | Number | 0.cc format |
| tippingAllowed | Boolean | |
| tipAmount | Number | 0.cc format |
| authorisationNumber | String | |
| referenceNumber | String | |
| rrn | String | |
| originalTransactionType | String | “Purchase” “Refund” |
| dateTime | String | ISO 8601 UTC format |
| settlementDate | String | MMdd |
| availableBalance | Number | 0.cc format |
| clearedFundsBalance | Number | 0.cc format |
Transactions
Registering a terminal
Example Register PINPad
curl "https://{{Environments}}/v1/pinpads" \
-H "Authorization: Bearer {accessToken}"
-X POST \
-d '{
"clientId": "100011002",
"password": "7809728256852118",
"pairingCode": "11100010001983"
}'
Returns response headers like so:
HTTP/1.1 200 Created
Content-Type: application/json
Date: Thu, 24 Apr 2014 15:17:53 GMT
Connection: keep-alive
The above command returns JSON structured like so:
{
"responseInfo": {
"successFlag": true,
"responseCode": "00",
"responseText": "APPROVED "
},
"pinPadInfo": {
"terminalId": "00019017001",
"dateTime": "2018-01-29T13:42:44.000+11:00",
"stan": 6210,
"aiic": "560254",
"serialNumber": "0000000075201724",
"versionNumber": "000842",
"timeout": 45,
"loggedOnFlag": false,
"eftposNetwork": "ANZPC-EFTPOS"
},
"merchants": [
{
"id": "00019017001",
"name": "DOCTOR ONE"
},
{
"id": "00019017101",
"name": "DOCTOR TWO"
},
{
"id": "00019017201",
"name": "DOCTOR THREE"
}
]
}
This endpoint registers the terminal to Practice location also known as PCEFTPOS cloud logon process.
As a user (admin) at a practice, I want to register a PINpad so that it can be used in this practice (or location)
Pre-requisite:
- valid token
User flow and requirements:
- PINpad must be present
- PINpad must be connected to the internet
- PINpad’s clientId, password and pairing code must be known.
- PINpad must also have done a bank logon once finished.
HTTP Request
POST https://{{Environments}}/v1/pinpads
HTTP Header
| Parameter | Description |
|---|---|
| accessToken | The access token. |
Body
| Parameter | type | Description |
|---|---|---|
| clientId | ID issued by PCEFTPOS for each terminal for cloud logon | |
| password | Password issued by PCEFTPOS for each terminal for cloud logon | |
| pairingCode | Pairing code is teh vaule retrieved from PCEFTPOS gateway using the terminal to pair it to the practice location. |
Response
Returns terminal data associated with the practice. This includes:
- Terminal Details
- Confirmation of registeration
- list of secondary merchants
| Parameter | type | Description |
|---|---|---|
| responseInfo | responseInfo | |
| pinPadInfo | pinPadInfo | Available information about the PINpad. |
| merchants | merchants | An Array of Merchant (if available). |
Removing a Registered terminal
Example Removing a Registered terminal
curl "https://{{Environments}}/v1/pinpads/{terminalId}" \
-H "Authorization: Bearer {accessToken}"
-X DELETE \
Returns response headers like so:
HTTP/1.1 200 Created
Content-Type: application/json
Date: Thu, 24 Apr 2014 15:17:53 GMT
Connection: keep-alive
The above command returns JSON structured like so:
{
"responseInfo": {
"successFlag": true
}
}
As a user (admin) at a practice, I want to removed a PINpad so that it cannot be used in this practice (or location).
Pre-requisite:
- valid token
HTTP Request
DELETE https://{{Environments}}/v1/pinpads/{terminalId}
HTTP Header
| Parameter | Description |
|---|---|
| accessToken | The access token. |
Response
| Parameter | type | Description |
|---|---|---|
| responseInfo | responseInfo |
Retrieve the Registered terminal list
Example Retrieve the Registered terminal list
curl "https://{{Environments}}/v1/pinpads" \
-H "Authorization: Bearer {accessToken}"
-X GET \
Returns response headers like so:
HTTP/1.1 200 Created
Content-Type: application/json
Date: Thu, 24 Apr 2014 15:17:53 GMT
Connection: keep-alive
The above command returns JSON structured like so:
{
"responseInfo": {
"successFlag": true
},
"pinPads": [
{
"terminalId": "00019017001",
"versionNumber": "000842"
}
]
}
As a PMS client, I want to get all PINpad registered in this practice (or location)
Pre-requisite:
- valid token
HTTP Request
GET https://{{Environments}}/v1/pinpads
HTTP Header
| Parameter | Description |
|---|---|
| accessToken | The access token. |
Response
| Parameter | type | Description |
|---|---|---|
| responseInfo | responseInfo | |
| pinPads | pinPadInfo | Available information about the PINpad. |
Perform a Bank logon
Example Perform a bank logon
curl "https://{{Environments}}/v1/pinpads/{terminalId}/logon" \
-H "Authorization: Bearer {accessToken}"
-X POST \
-d '{
"receiptPrinting": {
"printerType": "pinpad",
"cutReceipt": true
},
"logonType": "standard"
}'
Returns response headers like so:
HTTP/1.1 200 Created
Content-Type: application/json
Date: Thu, 24 Apr 2014 15:17:53 GMT
Connection: keep-alive
The above command returns JSON structured like so:
{
"responseInfo": {
"successFlag": true,
"responseCode": "00",
"responseText": "APPROVED "
},
"pinPadInfo": {
"terminalId": "00019017001",
"dateTime": "2018-01-30T11:23:33.000+11:00",
"stan": 6217,
"versionNumber": "000842"
},
"merchants": [{
"id": "00019017001",
"name": "PRIMARY"
}, {
"id": "00019017101",
"name": "DOCTOR ONE"
}, {
"id": "00019017201",
"name": "DOCTOR TWO"
}]
}
Prerequisites:
- valid token
- PINpad has been registered successfully to the practice
HTTP Request
POST https://{{Environments}}/v1/pinpads/{terminalId}/logon
HTTP Header
| Parameter | Description |
|---|---|
| accessToken | The access token. |
Body
| Parameter | type | Description |
|---|---|---|
| logonType | Standard Diagnostics RSA TMS_Full TMS_Params TMS_SW Logoff |
|
| receiptPrinting | receiptPrintingInfo | |
| purchaseAnalysisData | (optional). |
Response
| Parameter | type | Description |
|---|---|---|
| responseInfo | responseInfo | |
| pinPadInfo | pinPadInfo | Available information about the PINpad. |
| merchants | merchants | An Array of Merchant (if available). |
Query Card
Example of Query Card
curl "https://{{Environments}}/v1/pinpads/{terminalId}/query-card" \
-H "Authorization: Bearer {accessToken}"
-X GET \
Returns response headers like so:
HTTP/1.1 200 Created
Content-Type: application/json
Date: Thu, 24 Apr 2014 15:17:53 GMT
Connection: keep-alive
The above command returns JSON structured like so:
{
"responseInfo": {
"successFlag": true,
"responseCode": "00",
"responseText": "APPROVED"
},
"cardDataInfo": {
"track2": "610072=295102188=1=311219???????????????"
}
}
As a user at practice, I want to query a card to get the card value to submit a private health fund transaction.
User flow will be as per below:
- Receptions request for the processing of Private health claim
- Either Afterpay Touch Platform or PMS System initiates a card swipe request to terminal and present message to PMS to get the patient to swipe their health fund card
- Patient swipe the health fund card; terminal provide the card date to the either Afterpay Touch Platform or PMS System which is added to the claim request and sent to health funds for claim processing
NOTE: Afterpay Touch Platform will initiate the Swipe Healthfund Card request if the claim request submitted to Afterpay Touch does not have the Healthfund Card Track 2 data
Prerequisites:
- valid TOKEN
- PINpad has been registered successfully to the practice
HTTP Request
GET https://{{Environments}}/v1/pinpads/{terminalId}/query-card
HTTP Header
| Parameter | Description |
|---|---|
| accessToken | The access token. |
Response
| Parameter | type | Description |
|---|---|---|
| responseInfo | responseInfo | |
| cardDataInfo | cardDataInfo | Available information about the Card Swiped. |
Perform a transaction
Example of Purchase transaction
curl "https://{{Environments}}/v1/pinpads/{terminalId}/transactions" \
-H "Authorization: Bearer {accessToken}"
-X POST \
-d '{
"receiptPrinting": {
"printerType": "pinpad",
"cutReceipt": true
},
"transaction": {
"transactionType": "purchase",
"purchaseAmount": 1.00,
"referenceNumber": "1517195358087"
}
}'
Returns response headers like so:
HTTP/1.1 200 Created
Content-Type: application/json
Date: Thu, 24 Apr 2014 15:17:53 GMT
Connection: keep-alive
The above command returns JSON structured like so:
{
"responseInfo": {
"successFlag": true,
"responseCode": "00",
"responseText": "APPROVED "
},
"pinPadInfo": {
"merchant": "00",
"terminalId": "00019017201",
"stan": 6212
},
"transactionInfo": {
"transactionType": "Purchase",
"accountType": "Credit ",
"purchaseAmount": 1.00,
"cashAmount": 0.00,
"tipAmount": 0.00,
"authorisationNumber": "095250",
"referenceNumber": "1517195358087",
"rrn": "000000000045",
"dateTime": "2018-01-29T14:09:32.000+11:00",
"settlementDate": "2901"
},
"cardDataInfo": {
"cardType": "VISA",
"cardName": "04",
"pan": "4940520000006692",
"expiryDate": "1018",
"track2": "4940520000006692=1810???????????????????"
}
}
As a user at practice I want to be able to be able to process a card payment or refund transaction through my PMS using the ANZ Eftpos terminal utilising PC-EFTPOS Gateway Connect.
Prerequisites:
- valid TOKEN
- PINpad has been registered successfully to the practice
HTTP Request
POST https://{{Environments}}/v1/pinpads/{terminalId}/transactions
HTTP Header
| Parameter | Description |
|---|---|
| accessToken | The access token. |
Body
| Parameter | type | Description |
|---|---|---|
| transactionInfo | transactionInfo | |
| receiptPrintingInfo | receiptPrintingInfo |
Response
| Parameter | type | Description |
|---|---|---|
| responseInfo | responseInfo | |
| cardDataInfo | cardDataInfo | Available information about the Card Swiped. |
| transactionInfo | transactionInfo | |
| pinPadInfo | pinPadInfo | Available information about the PINpad. |
Example of Settlement transaction
curl "https://{{Environments}}/v1/pinpads/{terminalId}/settlement" \
-H "Authorization: Bearer {accessToken}"
-X POST \
-d '{
"receiptPrinting": {
"printerType": "pinpad",
"cutReceipt": true
},
"settlementType": "LastSettlement"
}'
Returns response headers like so:
HTTP/1.1 200 Created
Content-Type: application/json
Date: Thu, 24 Apr 2014 15:17:53 GMT
Connection: keep-alive
The above command returns JSON structured like so:
{
"responseInfo": {
"successFlag": true,
"responseCode": "00",
"responseText": "APPROVED "
},
"pinPadInfo": {
"merchant": "00",
"terminalId": "00019017201",
"stan": 6212
},
"transactionInfo": {
"transactionType": "Purchase",
"accountType": "Credit ",
"purchaseAmount": 1.00,
"cashAmount": 0.00,
"tipAmount": 0.00,
"authorisationNumber": "095250",
"referenceNumber": "1517195358087",
"rrn": "000000000045",
"dateTime": "2018-01-29T14:09:32.000+11:00",
"settlementDate": "2901"
},
"cardDataInfo": {
"cardType": "VISA",
"cardName": "04"
}
}
Events
In some cases, terminal will not send a response right away, but instead it will send EVENTS. This section describes different events and how to handle them.
Display Event
Example Display Event
{
"eventInfo": {
"displayText": ["INITIALISING ", "PLEASE WAIT "],
"okKeyFlag": false,
"cancelKeyFlag": false,
"yesKeyFlag": false,
"noKeyFlag": false,
"authoriseKeyFlag": false
}
}
This is determined by having “displayText” in “eventInfo”. it should display the text together which key or buttons are set to true.
Possible values of {keyPressType} are:
- okCancelKey (OK or CANCEL key was pressed. Note: OK and CANCEL key should not be displayed together)
- yesKey (YES key)
- noKey (NO key)
- authKey (reserved for future use)
Print Event
Example Print Event
{
"eventInfo": {
"receiptType": "Logon"
}
}
This is determine by “receiptType” or “receiptData” in “eventInfo”. This will happen if the request specifies the “printerType” is “pos”, see ReceiptPrintingInfo. Data to be printed is the “receiptData”.
This “eventInfo” must be handled accordingly or the request will be left in limbo.
Keep doing this until it receives “responseInfo”.
Errors
The Afterpay Touch Terminal Interface API uses the following error codes:
It uses conventional HTTP response codes to indicate success or failure of an API request.
In general, codes in the 2xx range indicate success, codes in the 4xx range indicate an error that resulted from the provided information (e.g. a required parameter was missing), and codes in the 5xx range indicate an error with the servers. Not all errors map cleanly onto HTTP response codes. Example, when a request is valid but does not complete successfully (e.g. a card is declined), we return a 402 error code.
RESPONSE
Returns a JSON response and appropriate HTTP status code
| Attributes | Description |
|---|---|
| Code | Error code. |
| Message | Error code description giving more details about the error. |
| status | The HTTP status code. |
| type | The type of error returned. Can be invalid_request_error, transaction_error, or server_error. |
| Error Code | Meaning |
|---|---|
| 400 | Bad Request – Your request is a little wrong |
| 401 | Unauthorized – Your API key is wrong |
| 402 | Your request was valid but failed a business process requirement. |
| 404 | Not Found – The specified resource could not be found |
| 405 | Method Not Allowed – You tried to access a resource with an invalid method |
| 406 | Not Acceptable – You requested a format that isn’t json |
| 410 | The resource requested has been removed from our servers |
| 422 | Unprocessable Entity – The request was well-formed but was unable to be followed due to semantic errors |
| 423 | Locked – The resource requested is in use at the moment. Try again later. |
| 429 | Too Many Requests – You’re requesting too many claims! Slown down! |
| 500 | Internal Server Error – We had a problem with our server. Try again later. |
| 503 | Service Unavailable – We’re temporarially offline for maintanance. Please try again later. |