Tap to Pay Transaction APIs
This guide documents the transaction-related backend APIs used in the Tap to Pay on iPhone flow:
- Submitting transactions (Purcahse & Refund)
- Handling SingleTapAndPIN (SCA)
All endpoints require a valid JWT as described in the JWT Integration Guide and use the standard header formats described in API Docs - Authentication.
1. Submit Apple Transaction
POST https://kernelserver.{env}.haloplus.io/transactions/apple
This is the primary endpoint used after a successful tap on the device. It submits the Apple Tap to Pay reader result to the Halo backend.
Path Parameters
| Name | Type | Description |
|---|---|---|
| env* | String | Backend environment [dev, qa, prod] |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| Authorization Bearer* | String | Yes | JWT generated by your backend (see JWT guide). Must represent the merchant user for this transaction. |
| Content-Type | String | Yes | application/json |
| X-Device-Installation-Id | String | Yes | Unique device installation identifier for the iOS device / reader. Used to bind transactions to a device. |
| X-Correlation-Id | String | No | Optional correlation ID (UUID) used for end‑to‑end tracing and log correlation. |
Request Body
The body is validated by the AppleTransaction schema and we expects the Apple Tap to Pay reader result data:
{
"merchantReference": "INV-12345", // Your transaction reference (required)
"generalCardData": "base64-encoded-string", // Apple general card data (Base64, required)
"paymentCardData": "base64-encoded-string" // Apple payment card data (Base64, required)
}
Request Field Descriptions
| Field | Type | Required | Description |
|---|---|---|---|
| merchantReference | String | Yes | Your transaction reference used to correlate the payment with your internal order/receipt. |
| generalCardData | String | Yes | Base64‑encoded Apple general card data blob. |
| paymentCardData | String | Yes | Base64‑encoded Apple payment card data blob used for authorisation. |
Responses
- 200: OK (Transaction Created)
- 201: Created (Waiting for PIN)
- 201: Created (Declined)
- 500: Internal Server Error
{
"onlineAuthorizationResponse": {
"type": "Approved",
"authorizationCode": "543312",
"tags": [],
"haloReference": "62e557d5-fdf3-4f07-a4cb-0c67e128f17e",
"errorMessage": "Transaction approved",
"errorCode": 0,
"isoResponseCode": "00",
"association": "1234567890",
"expiryDate": "",
"paymentProviderReference": "03974615",
"cardType": "Credit Card",
"cardScheme": "Visa",
"customValues": {},
"isSingleTapAndPin": false,
"maskedPAN": "476173******0027",
"pinToken": "1234567890",
"cardReaderId": "1234567890",
"cardReaderTransactionId": "82669000000001"
}
}
{
"onlineAuthorizationResponse": {
"type": "Declined",
"authorizationCode": "",
"tags": [],
"haloReference": "62e557d5-fdf3-4f07-a4cb-0c67e128f17e",
"errorMessage": "Exceeds withdrawal frequency limit",
"errorCode": 65,
"isoResponseCode": "65",
"association": "1234567890",
"expiryDate": "",
"paymentProviderReference": "",
"cardType": "Credit Card",
"cardScheme": "Visa",
"customValues": {},
"isSingleTapAndPin": true, // Lookout for this flag
"maskedPAN": "476173******0027",
"pinToken": "1234567890",
"cardReaderId": "1234567890",
"cardReaderTransactionId": "622e42d5-fdf3-4f07-a4cb-0c67e128f12"
}
}
{
"onlineAuthorizationResponse": {
"type": "Declined",
"authorizationCode": "",
"tags": [],
"haloReference": "62e557d5-fdf3-4f07-a4cb-0c67e128f17e",
"errorMessage": "The payment provider declined the transaction",
"errorCode": 209,
"isoResponseCode": "91",
"association": "1234567890",
"expiryDate": "",
"paymentProviderReference": "",
"cardType": "Credit Card",
"cardScheme": "Visa",
"customValues": {},
"isSingleTapAndPin": false,
"maskedPAN": "476173******0027",
"pinToken": "1234567890",
"cardReaderId": "1234567890",
"cardReaderTransactionId": "622e42d5-fdf3-4f07-a4cb-0c67e128f12"
}
}
{
"error": "Internal server error"
}
Key behaviour:
- If PIN is required (SCA / SingleTapAndPIN):
isSingleTapAndPinistrueandpinToken(For Mastercard) is present- You must call Submit Apple PIN (SCA) with the
transactionId/haloReferenceandpinToken
- If no PIN is required:
isSingleTapAndPinis typicallyfalse- The transaction can be considered final from the device perspective
See Common Response: onlineAuthorizationResponse.
2. Submit Apple PIN (SCA)
POST https://kernelserver.{env}.haloplus.io/transactions/:transactionId/submitPinApple
Use this endpoint when the initial Apple transaction response indicates that PIN is required (isSingleTapAndPin = true).
Path Parameters
| Name | Type | Description |
|---|---|---|
| env* | String | Backend environment [dev, qa, prod] |
| :transactionId* | String | Transaction identifier (haloReference) returned from Submit Apple Transaction |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| Authorization Bearer* | String | Yes | JWT generated by your backend (see JWT guide). Must represent the merchant user for this transaction. |
| Content-Type | String | Yes | application/json |
| X-Device-Installation-Id | String | Yes | Unique device installation identifier for the iOS device / reader. Used to bind transactions to a device. |
| X-Correlation-Id | String | No | Optional correlation ID (UUID) used for end‑to‑end tracing and log correlation. |
Request Body
Validated by the same AppleTransaction schema used for Submit Apple Transaction. The SDK sends updated Apple payload data for the PIN/SCA attempt in the same structure:
{
"merchantReference": "INV-12345", // Your transaction reference (same as initial transaction)
"generalCardData": "base64-encoded-string", // Updated Apple general card data (Base64)
"paymentCardData": "base64-encoded-string" // Updated Apple payment card data (Base64, now including PIN/SCA result)
}
Responses
- 201: Created (Approved)
- 201: Created (Declined)
- 500: Internal Server Error
{
"onlineAuthorizationResponse": {
"type": "Approved",
"authorizationCode": "123456",
"tags": [],
"haloReference": "abcd-1234",
"errorMessage": "Transaction approved",
"errorCode": 0,
"isoResponseCode": "00",
"association": "1234567890",
"expiryDate": "",
"paymentProviderReference": "03974615",
"cardType": "Credit Card",
"cardScheme": "Visa",
"customValues": {},
"isSingleTapAndPin": false,
"maskedPAN": "476173******0027"
}
}
{
"onlineAuthorizationResponse": {
"type": "Declined",
"authorizationCode": "",
"tags": [],
"haloReference": "abcd-1234",
"errorMessage": "Invalid PIN data",
"errorCode": 211,
"isoResponseCode": "65",
"association": "1234567890",
"expiryDate": "",
"paymentProviderReference": "",
"cardType": "Credit Card",
"cardScheme": "Visa",
"customValues": {},
"isSingleTapAndPin": true,
"maskedPAN": "476173******0027"
}
}
{
"error": "Internal server error"
}
Response Field Descriptions
See Common Response: onlineAuthorizationResponse.
3. Referenced APIs
For the full, generic transaction history API and additional filters, see:
Notes and Best Practices
- Always use HTTPS for all backend calls.
- Treat unknown JSON fields as optional – new fields may be added over time.
- Use
merchantReferenceconsistently so that refund and reference‑check flows behave as expected. - Log the
haloReferencefor every transaction; it is required for refunds, voids, and receipt lookups.
Common Response: onlineAuthorizationResponse
Error Conditions
- 401 Unauthorized: Missing, invalid, or expired
AuthorizationJWT. - 403 Forbidden: JWT user is authenticated but not permitted to submit PIN for this transaction.
- 4xx Validation Error: Request body fails schema validation (for example, missing or invalid
pinToken/pinBlock). - 409 Conflict: PIN submitted for a transaction that is not in a PIN‑waiting state (already finalised or invalid state).
- 500 Internal Server Error: Backend error while processing SCA with the payment provider or updating the transaction.
| Field | Type | Description |
|---|---|---|
| onlineAuthorizationResponse | Object | Wrapper object containing the online authorisation response for this transaction |
| onlineAuthorizationResponse.haloReference | String | Halo backend transaction identifier (use this for follow‑up calls) |
| onlineAuthorizationResponse.type | String | High‑level disposition (Approved, Declined, Indeterminate, etc.) |
| onlineAuthorizationResponse.authorizationCode | String | Processor authorisation code when approved (may be empty/omitted on declines) |
| onlineAuthorizationResponse.tags | Array | Raw tag list returned from the payment provider (for advanced / EMV use cases) |
| onlineAuthorizationResponse.isSingleTapAndPin | Boolean | Indicates whether SCA (PIN) is required for this transaction |
| onlineAuthorizationResponse.pinToken | String | Token used in the Submit Apple PIN call when SCA is required (primarily for Mastercard flows) |
| onlineAuthorizationResponse.cardReaderId | string | Identifier for the Apple proximity reader used in the transaction |
| onlineAuthorizationResponse.cardReaderTransactionId | string | Apple proximity reader transaction Identifier |
| onlineAuthorizationResponse.amount | Number | Transaction amount in minor units |
| onlineAuthorizationResponse.currency | String | ISO currency code, e.g. ZAR |
| onlineAuthorizationResponse.merchantReference | String | Your original merchant transaction reference |
| onlineAuthorizationResponse.cardScheme | String | Card scheme (e.g. Visa, Mastercard) |
| onlineAuthorizationResponse.cardType | String | Card type (e.g. Credit Card, Debit Card) |
| onlineAuthorizationResponse.maskedPAN | String | Masked primary account number |
| onlineAuthorizationResponse.isoResponseCode | String | ISO‑8583 response code from the payment provider (e.g. 00, 65, 91) |
| onlineAuthorizationResponse.association | String | Optional association / reference value returned by the payment provider |
| onlineAuthorizationResponse.expiryDate | String | Optional card expiry date as returned by the payment provider |
| onlineAuthorizationResponse.paymentProviderReference | String | Optional payment‑provider specific reference ID |
| onlineAuthorizationResponse.customValues | Object | Optional provider‑specific or acquirer‑specific custom values |
| onlineAuthorizationResponse.errorCode | Number | Optional numeric error code when type is Declined (for example 211 = InvalidPinData) |
| onlineAuthorizationResponse.errorMessage | String | Optional human‑readable message when type is Declined |