Afterpay In-Store AU API v1
Document Version 4.2 | Last updated: Thursday, 02 May, 2019
API Production Endpoint
https://posapi.afterpay.com/v1/
API Test Endpoint
https://posapi-sandbox.afterpay.com/v1/
This document details the Afterpay In-Store API.
REST
The Afterpay In-Store API is organized around REST. The API attempts to use predictable, resource-oriented URLs and to use HTTP response codes to indicate errors.
HTTPS
The Afterpay In-Store API requires all communications to be secured using TLS 1.2 or greater.
Request Headers
Clients must use request headers accordingly:
- All
GET
requests return JSON and thus must set compatible accept headers, eitherapplication/json
or*/*
.
Dates
All representations of dates are strings in ISO 8601 format.
You can provide date strings that are either UTC (for example, 2015-01-01T00:00:00Z
) or offset from UTC to indicate time zone (for example, 2015-01-01T00:00:00-08:00
for eight hours behind UTC).
POS Authentication
To authorize, use this code:
# With shell, you can just pass the correct header with each request. An example request:
curl "https://posapi-sandbox.afterpay.com/v1/" \
-H 'Authorization: Bearer <deviceAccessToken>'
Make sure to replace
deviceAccessToken
a valid access token.
The Afterpay In-Store API uses access tokens to allow access to the API. Access tokens are created using the Create Token endpoint.
The Afterpay In-Store API expects the access token to be included in all API requests as a HTTP header that looks like the following:
Authorization: Bearer <deviceAccessToken>
POS Operator Identification
# With shell, you can just pass the correct header with each request
curl "https://posapi-sandbox.afterpay.com/v1/" \
-H "Operator: operator-id"
Make sure to replace
operator-id
with the operator’s ID.
With the exception of the device activation and create token endpoints, Afterpay expects for the Operator ID to be included in all posapi.afterpay.com
API requests to the server in a header that looks like the following:
Operator: operator-id
Idempotent Requests
The Afterpay In-Store API supports idempotency that allows the safe retry of requests guaranteeing the operation is only performed once.
If for example an order request fails with a network error, the request can be retried with the same requestId
.
We recommend that you use UUIDs as request IDs. The resources that include a requestId
will send back the same response for requests made with the same requestId
for up to 24 hours.
Distributed State Considerations
It is important that integrators consider all failure scenarios associated with sending an order/refund request over the network, which is inherently unreliable.
Afterpay recommends the following implementation steps to guard against state inconsistencies between the POS and Afterpay:
- Before attempting an order/refund request the POS client should generate a request ID and store to durable disk.
- The POS client should perform an order/refund request using the established requestId.
- Should the request succeed the stored request ID can be removed.
- Should a response not be received within 30 seconds the POS can opt to retry the idempotent order/refund request. If the original order/refund is still processing the API will return a 409 conflict error otherwise a sucess response will be returned on retry.
- Should subsequent retries fail to return a success or error response (with exception to 409 conflict), the POS should queue the request ID for reversal. The implementation should consider power failure scenarios that would require the POS to reverse any unacknowledged order/refund requests on POS startup.
Timeouts
Afterpay will attempt to respond to requests as soon as possible, but often latency delays are outside of our control. Where an API call is dependant on downstream banking networks the response times can be higher. As a guideline this document provides recommended network connection open timeout and read timeout values for each API resource. Resources that are dependant on banking networks will have higher timeout values. All resources that are identified as idempotent can be safely retried before the recommended timeout periods.
Models
Money object
Example money object
{
"amount": "29.99",
"currency": "AUD"
}
Attributes
Parameter | Type | Description |
---|---|---|
amount | string | The amount should be a string representation of a decimal number. Unless otherwise indicated the precision should be the standard precision for the currency of the amount. |
currency | string | The currency is a ISO 4217 format value. Currently only AUD is supported. |
Item object
Represents an item in the order. All fields are required.
Example item object
{
"name": "widget",
"sku": "123412234",
"quantity": 1,
"price": {
"amount": "10.00",
"currency": "AUD"
}
}
Attributes
Parameter | Type | Description |
---|---|---|
name | string | A name of the item. |
sku | string | The SKU of the item. |
quantity | number | The number of items purchased. |
price | Money | The unit price of the individual item. Must be a positive value. |
Service Status
Ping
This endpoint can be used to check that the service is reachable and available.
Example Ping Request
curl "https://posapi-sandbox.afterpay.com/ping"
Response (200)
HTTP Request
GET /ping
Device Authentication
Device Activation
Example Device Activation Request
curl "https://posapi-sandbox.afterpay.com/v1/devices/activate" \
-X POST \
-H 'Content-Type: application/json' \
-H 'User-Agent: Merchant XYZ; POS Platform/1.0.0; Merchant/60032000' \
-H 'Accept: application/json' \
-d '{
"secret":"111333331001",
"name": "POS1234",
"attributes": {
"terminal": "NCR",
"hardwareId": "678678"
}
}'
Response (201)
{
"deviceId":1234,
"key":"apikey_bb68452ad2d743db75a270bf2c305df9abeefc"
}
This endpoint performs a one time activation of a device, providing a device’s identification and authorization credentials. 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 /v1/devices/activate
HTTP Headers
Parameter | Description |
---|---|
Content-Type | application/json |
User-Agent | {merchantName} ; {platform} /{platformVersion} ; Merchant/{merchantId} |
Accept | application/json |
Arguments
Parameter | Type | Description |
---|---|---|
secret | required string |
The terminal secret provided for activation. |
name | required string |
An identifier for the terminal being activated. |
attributes | optional |
A map that can be populated with device specific information. |
Response
Returns the device’s authorization credentials
Parameter | Description |
---|---|
deviceId | A device ID required for auditing and authentication. |
key | A secret key required for authentication. |
Errors
Can return the following specific error responses
Status Code | Type | Description |
---|---|---|
401 | unauthorized | Will be returned if the secret is invalid for the device name. |
Connection timeouts
Timeout | Time (seconds) |
---|---|
Open | 10 |
Read | 20 |
Create Token
Example Create Token Request
curl "https://posapi-sandbox.afterpay.com/v1/devices/123/token" \
-X POST \
-H 'Content-Type: application/json' \
-H 'User-Agent: Merchant XYZ; POS Platform/1.0.0; Merchant/60032000' \
-H 'Accept: application/json' \
-d '{
"key":"bb68452ad2d743db75a270bf2c305df9abeefcb3e02084fc1ff7a3ba61ed46d5"
}'
Response (201)
{
"token":"86bc8b2b973d5046d82432862254dfb5967a6db7c844bf615ab8eba17082105b",
"expiresIn":85800
}
This endpoint creates a device access token. The device will need to periodically renew the access token, indicated by expiresIn, required by all API endpoints.
HTTP Request
POST /v1/devices/{deviceId}/token
URL Parameters
Parameter | Description |
---|---|
deviceId | The device ID obtained during activation |
HTTP Headers
Parameter | Description |
---|---|
Content-Type | application/json |
User-Agent | {merchantName} ; {platform} /{platformVersion} ; Merchant/{merchantId} |
Accept | application/json |
Arguments
Parameter | Description |
---|---|
key | The device secret key obtained during activation |
Response
Returns the devices access token
Parameter | Description |
---|---|
token | An access token. |
expiresIn | The access token’s expiry time in seconds. |
Errors
Can return the following specific error responses
Status Code | Type | Description |
---|---|---|
401 | unauthorized | Will be returned if the secret is invalid. |
Connection timeouts
Timeout | Time (seconds) |
---|---|
Open | 10 |
Read | 20 |
Order (Payment)
Create Order
Example Order Request
curl "https://posapi-sandbox.afterpay.com/v1/orders" \
-X POST \
-H 'Authorization: Bearer 86bc8b2b973d5046d82432862254dfb5967a6db7c844bf615ab8eba17082105b' \
-H 'Content-Type: application/json' \
-H 'Operator: Dante Hicks' \
-H 'User-Agent: Merchant XYZ; POS Platform/1.0.0; Merchant/60032000; Device/100' \
-H 'Accept: application/json' \
-d '{
"requestId":"61cdad2d-8e10-42ec-a97b-8712dd7a8ca9",
"requestedAt":"2015-07-14T10:08:14.123Z",
"preApprovalCode":"12FA1G3C2E9D",
"amount": {
"amount": "15.00",
"currency": "AUD"
},
"merchantReference": "123987",
"orderItems": [
{
"name": "widget",
"sku": "123412234",
"quantity": 1,
"price": {
"amount": "10.00",
"currency": "AUD"
}
},
{
"name": "blob",
"sku": "123324u4",
"quantity": 1,
"price": {
"amount": "5.00",
"currency": "AUD"
}
}
]
}'
Response (201)
{
"orderId":"100012",
"orderedAt":"2015-07-14T10:08:15.456Z",
"requestId":"61cdad2d-8e10-42ec-a97b-8712dd7a8ca9",
"requestedAt":"2015-07-14T10:08:14.123Z",
"preApprovalCode":"12FA1G3C2E9D",
"amount": {
"amount": "15.00",
"currency": "AUD"
},
"merchantReference": "123987",
"orderItems": [
{
"name": "widget",
"sku": "123412234",
"quantity": 1,
"price": {
"amount": "10.00",
"currency": "AUD"
}
},
{
"name": "blob",
"sku": "123324u4",
"quantity": 1,
"price": {
"amount": "5.00",
"currency": "AUD"
}
}
]
}
This resource creates an order.
HTTP Request
POST /v1/orders
HTTP Headers
Parameter | Description |
---|---|
Authorization | The Bearer token returned from /v1/devices/token . |
Content-Type | application/json |
Operator | The POS/Terminal Operator ID. |
User-Agent | {merchantName} ; {platform} /{platformVersion} ; Merchant/{merchantId} ; Device/{deviceId} |
Accept | application/json |
Arguments
Parameter | Type | Description |
---|---|---|
requestId | string | A client created unique request ID. It is recommended that the client generate a GUID as no mechanism is provided to synchronise a incrementing id should the sequence repeat. |
requestedAt | string (ISO-8601) | A timestamp of the client order payment request time (ISO 8601 UTC/Zulu time). |
merchantReference | string | A reference id linking this order payment to an object in the merchant’s system. For example the POS basket ID. |
preApprovalCode | string | The pre-approval alphanumeric code obtained from the barcode displayed on the customers mobile. |
amount | Money | The payment amount. |
orderItems | Item[] required |
A list of order items. |
Response
Returns the order response. In addition to returning all fields present in the request, the response will also include the following two new fields.
Parameter | type | Description |
---|---|---|
orderId | string | The order ID is a unique numerical ID suitable for inclusion on a customer invoice. |
orderedAt | string (ISO-8601) | A timestamp of the completed transaction (ISO 8601 UTC/Zulu time). |
- All request parameters will be echoed in the response.
Errors
Can return the following specific error responses in addition to general errors outlined below.
Status Code | Error Code | Description |
---|---|---|
402 | declined | transaction declined. |
402 | minimum_not_met | order amount is below the minimum pre-approval amount. |
402 | exceed_preapproval | order amount exceeded pre-approval amount. |
409 | conflict | Another request with this request id is currently being processed. |
412 | invalid_code | Will be returned if the code: has expired, has been used, is invalid. |
- Should a success or error response (with exception to 409 conflict) not be received, the POS should queue the request ID for reversal. Please see sections Idempotent Requests and Distributed State Considerations for further details.
Connection timeouts
Timeout | Time (seconds) |
---|---|
Open | 10 |
Read | 70 |
Reverse Order
Example Order Reversal Request
curl "https://posapi-sandbox.afterpay.com/v1/orders/reverse" \
-X POST \
-H 'Authorization: Bearer 86bc8b2b973d5046d82432862254dfb5967a6db7c844bf615ab8eba17082105b' \
-H 'Content-Type: application/json' \
-H 'Operator: Dante Hicks' \
-H 'User-Agent: Merchant XYZ; POS Platform/1.0.0; Merchant/60032000; Device/100' \
-H 'Accept: application/json' \
-d '{
"requestedAt":"2015-07-14T10:08:14Z",
"reversingRequestId":"61cdad2d-8e10-42ec-a97b-8712dd7a8ca9"
}'
Response (202)
{
"reverseId":"100020",
"reversedAt":"2015-07-14T10:08:15.456Z",
"requestedAt":"2015-07-14T10:08:14Z",
"reversingRequestId":"61cdad2d-8e10-42ec-a97b-8712dd7a8ca9"
}
This resource reverses a previous order.
Reversals are system level requests that ensure network failures don’t result in inconsistent state between the client and server. The client should send a reversal if it doesn’t received a response within 30 seconds. Reversals are idempotent.
HTTP Request
POST /v1/orders/reverse
HTTP Headers
Parameter | Description |
---|---|
Authorization | The Bearer token returned from /v1/devices/token . |
Content-Type | application/json |
Operator | The POS/Terminal Operator ID. |
User-Agent | {merchantName} ; {platform} /{platformVersion} ; Merchant/{merchantId} ; Device/{deviceId} |
Accept | application/json |
Arguments
Parameter | Type | Description |
---|---|---|
requestedAt | required string (ISO 8601) |
A timestamp of the client order request time (ISO 8601 UTC/Zulu time). |
reversingRequestId | required string |
The request ID for the previous submitted order request. |
Response
Returns the reversal response
Parameter | Type | Description |
---|---|---|
reverseId | string | The reversal ID. |
reversedAt | string (ISO-8601) | A timestamp of the completed reversal transaction. |
- All request parameters will be echoed in the response.
Errors
Can return the following specific error responses
Status Code | Error Code | Description |
---|---|---|
412 | precondition_failed | The reversingRequestId was not found. This might occur if the initial request was never received by the server or the reversal request occurs after 24 hours of the original request. |
Connection timeouts
Timeout | Time (seconds) |
---|---|
Open | 10 |
Read | 20 |
Refund
Create Refund
Example Refund Request
curl "https://posapi-sandbox.afterpay.com/v1/refunds" \
-X POST \
-H 'Authorization: Bearer 86bc8b2b973d5046d82432862254dfb5967a6db7c844bf615ab8eba17082105b' \
-H 'Content-Type: application/json' \
-H 'Operator: Dante Hicks' \
-H 'User-Agent: Merchant XYZ; POS Platform/1.0.0; Merchant/60032000; Device/100' \
-H 'Accept: application/json' \
-d '{
"requestId": "7c4bdcd7-09b2-4a2d-a7cb-5017b621d6f7",
"requestedAt": "2015-07-14T10:08:14.123Z",
"merchantReference": "123987",
"orderId": "100015",
"orderMerchantReference": "100012",
"amount": {
"amount": "10.00",
"currency": "AUD"
}
}'
Response (201)
{
"refundId": "100016",
"refundedAt": "2015-07-14T10:08:15.456Z",
"requestId": "7c4bdcd7-09b2-4a2d-a7cb-5017b621d6f7",
"requestedAt": "2015-07-14T10:08:14.123Z",
"merchantReference": "123987",
"orderId": "100015",
"orderMerchantReference": "100012",
"amount": {
"amount": "10.00",
"currency": "AUD"
}
}
This resource performs a full or partial refund.
HTTP Request
POST /v1/refunds
HTTP Headers
Parameter | Description |
---|---|
Authorization | The Bearer token returned from /v1/devices/token . |
Content-Type | application/json |
Operator | The POS/Terminal Operator ID. |
User-Agent | {merchantName} ; {platform} /{platformVersion} ; Merchant/{merchantId} ; Device/{deviceId} |
Accept | application/json |
Arguments
Parameter | Type | Description |
---|---|---|
requestId | required string |
A client created unique request ID. It is recommended that the client generate a GUID as no mechanism is provided to synchronise a incrementing id should the sequence repeat. |
requestedAt | required string (ISO-8601) |
A timestamp of the client refund request time (ISO 8601 UTC/Zulu time). |
merchantReference | optional string |
A reference id linking this refund to an object in the merchant’s system. For example the POS refund ID. |
orderId | required string |
The original order ID to apply the refund to |
orderMerchantReference | optional string |
The original Order’s merchantReference. If the supplied value does not match the original Order a error will be returned. |
amount | required Money |
The refund amount. The refund amount can not exceed the associated order. |
Response
Returns the refund response. In addition to the fields in the original request, the response includes the following:
Parameter | Type | Description |
---|---|---|
refundId | string | The refund ID is a unique numerical ID suitable for inclusion on a customer invoice. |
refundedAt | string (ISO-8601) | A timestamp of the completed refund transaction. |
- All request parameters will be echoed in the response.
Errors
Can return the following specific error responses
Status Code | Error code | Description |
---|---|---|
409 | conflict | Another request with this request id is currently being processed. |
412 | invalid_order_merchant_reference | The supplied orderMerchantReference did not match the original Order. |
412 | precondition_failed | The orderId was not found or was not eligible for a refund. |
422 | invalid_amount | The sum of all refunds for the given order, including the new refund, exceed the initial order amount. |
- Should a success or error response (with exception to 409 conflict) not be received, the POS should queue the request ID for reversal. Please see sections Idempotent Requests and Distributed State Considerations for further details.
Connection timeouts
Timeout | Time (seconds) |
---|---|
Open | 10 |
Read | 20 |
Refund Reversal
Example Reverse Refund Request
curl "https://posapi-sandbox.afterpay.com/v1/refunds/reverse" \
-X POST \
-H 'Authorization: Bearer 86bc8b2b973d5046d82432862254dfb5967a6db7c844bf615ab8eba17082105b' \
-H 'Content-Type: application/json' \
-H 'Operator: Dante Hicks' \
-H 'User-Agent: Merchant XYZ; POS Platform/1.0.0; Merchant/60032000; Device/100' \
-H 'Accept: application/json' \
-d '{
"requestedAt":"2015-07-14T10:08:14.123Z",
"reversingRequestId":"7c4bdcd7-09b2-4a2d-a7cb-5017b621d6f7"
}'
Response (202)
{
"reverseId":"100018",
"reversedAt":"2015-07-14T10:08:15.456Z",
"requestedAt":"2015-07-14T10:08:14.123Z",
"reversingRequestId":"7c4bdcd7-09b2-4a2d-a7cb-5017b621d6f7"
}
This resource reverses a previous refund.
Reversals are system level requests that ensure network failures don’t result in inconsistent state between the client and server. The client should send a reversal if it doesn’t received a response within 40 second. Reversals are idempotent.
HTTP Request
POST /v1/refunds/reverse
HTTP Headers
Parameter | Description |
---|---|
Authorization | The Bearer token returned from /v1/devices/token . |
Content-Type | application/json |
Operator | The POS/Terminal Operator ID. |
User-Agent | {merchantName} ; {platform} /{platformVersion} ; Merchant/{merchantId} ; Device/{deviceId} |
Accept | application/json |
Arguments
Parameter | Type | Description |
---|---|---|
requestedAt | required string (ISO-8601) |
A timestamp of the client refund request time (ISO 8601 UTC/Zulu time). |
reversingRequestId | required string |
The request ID for the previous submitted refund request. |
Response
Returns the reversal response
Parameter | Type | Description |
---|---|---|
reverseId | string | The reversal ID. |
reversedAt | string (ISO-8601) | A timestamp of the completed reversal transaction. |
- All request parameters will be echoed in the response.
Errors
Can return the following specific error responses
Status Code | Error Code | Description |
---|---|---|
412 | precondition_failed | The reversingRequestId was not found. This might occur if the initial request was never received by the server or the reversal request occurs after 24 hours of the original request. |
Connection timeouts
Timeout | Time (seconds) |
---|---|
Open | 10 |
Read | 20 |
Errors
Example Invalid Create Purchase Request
curl "https://example.afterpay.com/v1/example" \
-X POST \
-d '{
"amount": {
"amount": "-250.15",
"currency": "AUD"
}
},'
If the given parameters are incorrect, you will receive a HTTP 400 response
HTTP/1.1 400 Bad Request
Cache-Control: must-revalidate,no-cache,no-store
Content-length: 1327
Content-Type: text/html;charset=ISO-8859-1
Date: Thu, 24 Apr 2014 15:15:11 GMT
Connection: keep-alive
The above command returns JSON structured like so:
{
"errorCode" : "invalid_object",
"errorId" : "cf5907fbf8fbc417",
"message" : "[totalAmount must be greater than 0.00 (was AUD -250.15)]",
"httpStatusCode" : 422
}
The Afterpay API 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 Afterpay servers.
Response
Returns a JSON response and appropriate HTTP status code
Attributes | description |
---|---|
httpStatusCode | The HTTP status code |
errorId | A unique error ID. |
errorCode | The type of error returned. For example, invalid_object, transaction_error, or server_error. |
message | A human-readable message giving more details about the error. For card errors, these messages can be shown to your users. |
Some examples of status codes that might be returned by the Afterpay API are below. This list is not exhaustive, and other status codes may be encountered specific to the resource.
HTTP Status Code | HTTP Status Name | Meaning |
---|---|---|
400 | Bad Request | Your request is a little wrong. |
401 | Unauthorized | Your API key is wrong or access token is invalid. |
402 | Payment Required | Generally returned in cases where payments are declined. |
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. |
409 | Conflict | You tried to perform an operation that conflicts with another operation. |
410 | Gone | The resource requested has been removed from our servers. |
412 | Precondition Failed | A prerequisite step that was required before calling the resource had not been performed. |
422 | Unprocessable Entity | The request format was valid, however one or more values were incorrect. |
429 | Too Many Requests | Too many requests may occur if an abnormal number of requests occur. |
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. |