Notification
Backend notification sent by 2C2P to your server after each SoftPOS transaction
After a SoftPOS transaction completes, 2C2P sends a backend notification to your server. This notification delivers the authoritative transaction result and is the recommended source of truth for updating your order and ledger systems.
Notifications apply to all SoftPOS integration modes that involve a merchant backend: Mobile SDK, Device-to-App, and App-to-App. Standalone App mode does not send backend notifications.
How it works
%%{init: {'theme': 'base', 'themeVariables': {'actorBkg': '#e8ecf2', 'actorTextColor': '#00112c', 'actorBorderColor': '#004f5c', 'signalColor': '#0088FF', 'signalTextColor': '#333333', 'activationBkgColor': '#dff0f2', 'activationBorderColor': '#004f5c', 'noteBkgColor': '#f2f2f2', 'noteTextColor': '#00112c', 'noteBorderColor': '#004f5c'}}}%%
sequenceDiagram
participant POS as SoftPOS
participant PGW as 2C2P PGW
participant Backend as Your Server
POS->>PGW: Process transaction
activate PGW
PGW-->>POS: Synchronous result
deactivate PGW
PGW->>Backend: POST /your-notification-endpoint
activate Backend
Note over Backend: 1. Verify JWT signature<br/>2. Decode payload<br/>3. Match by invoiceNo<br/>4. Update order status
Backend-->>PGW: HTTP 200 OK
deactivate Backend
- A transaction completes on the SoftPOS device.
- 2C2P sends an HTTP POST to your pre-configured notification endpoint.
- Your server verifies the JWT signature, decodes the payload, and updates the order status.
- Your server responds with HTTP 200 to acknowledge receipt.
Endpoint requirements
You must provide 2C2P with a notification endpoint URL during onboarding. The endpoint must meet the following requirements:
| Requirement | Detail |
|---|---|
| Method | POST |
| Content-Type | application/json |
| Protocol | HTTPS (TLS 1.2 or higher) |
| Response | HTTP 200 OK within 30 seconds. |
| Timeout | Process and respond within 30 seconds. Defer long-running work to an async queue. |
Notification structure
Each notification is a JSON object with the following envelope fields:
| Field | Data Type | Mandatory | Description |
|---|---|---|---|
| category | enum | M | Notification category. Possible value: PAYMENT. |
| event | enum | M |
Transaction event type:
|
| version | String | M | API version of the notification format (e.g. "4.3"). |
| payload | String | M | JWT-encoded transaction details. Decode and verify the signature before processing. The decoded payload matches the v4 inquiry response structure. |
| invoiceNo | String | M | Merchant invoice number. |
| respCode | String | M | Response code. "0000" indicates success. See Response Codes. |
| respDesc | String | M | Human-readable response description (e.g. "Success"). |
Payload fields (decoded JWT)
The payload field is a signed JWT. After verifying the signature and decoding the claims, the payload matches the v4 Inquiry API response structure.
|
Parameter |
Data Type |
Mandatory |
Description |
||
|---|---|---|---|---|---|
|
merchantID |
C 25 |
M |
Merchant ID |
||
| childMerchantID | AN 25 | C | Unique merchant ID that is registered with 2C2P, must be SUB Account of merchantID | ||
|
invoiceNo |
AN 50 |
M |
Invoice number Unique merchant order number. |
||
|
amount |
D (12,5) |
M |
Transaction amount |
||
|
currencyCode |
A 3 |
M |
Currency Code. Transaction currency code in 3 alphabet value as specified in ISO 4217. SGD = Singapore dollar if empty, default value will use merchant's base currency. |
||
|
transactionDateTime |
N 14 |
M |
Process transaction Date Time Note : Date format “ yyyyMMddHHmmss” |
||
|
agentCode |
AN 30 |
M |
Agent code, it’s the agent who process the payment. Refer to Agent code List |
||
|
channelCode |
AN 30 |
M |
Channel code list: Refer to Process By / Channel Code List |
||
|
approvalCode |
C 6 |
C |
Approval code of transaction. mandatory for credit card payment |
||
|
referenceNo |
AN 50 |
M |
Transaction Reference Number from Credit Card Host. |
||
|
tranRef |
AN 28 |
O |
Issued by System. This is to trace the transactions in the Routing System. |
||
|
accountNo |
N 19 |
M |
masked credit card number. first 6 and last 4 of credit card number |
||
|
customerToken |
AN 20 |
O |
Unique ID of store card info (generated and returned by 2c2p payment gateway if payment send with storeCard option value is "Y"). Only for credit card payment. |
||
|
customerTokenExpiry |
AN 8 |
O |
Token expiry date. Format: yyyyMMdd |
||
|
cardType |
C 20 |
C |
Card type as retrieved based on BIN information
- PREPAID - DEBIT - CREDIT |
||
|
issuerCountry |
A 2 |
C |
credit card bank issuer country. A2 country code mandatory for credit card |
||
|
issuerBank |
C 200 |
C |
credit card bank issuer name. |
||
|
eci |
C 2 |
C |
ECI for credit card payment. mandatory for credit card payment |
||
|
installmentPeriod |
N 2 |
C |
Installment tenor |
||
|
interestType |
A 1 |
C |
Installment interest type |
||
|
interestRate |
D (3,5) |
C |
Installment interest rate |
||
|
installmentMerchantAbsorbRate |
D (3,5) |
C |
Installment merchant absorb rate |
||
|
recurringUniqueID |
N 20 |
C |
RPP transaction record identifier. Mandatory for RPP transaction. |
||
|
recurringSequenceNo |
N 10 |
C |
To indicate the number of recurring payments. eg. recurringSequenceNo = 8 means this recurring payment is 8th time from the recurring cycle. Mandatory for RPP transaction. |
||
|
fxAmount |
D(12,5) |
C |
mcp Amount |
||
|
fxRate |
D(12,7) |
C |
mcp Fx Rate |
||
|
fxCurrencyCode |
A3 |
C |
mcp Currency Code |
||
| userDefined1 | C 150 | O | For merchant to submit merchant's specific data. | ||
|
userDefined2 |
C 150 |
O |
For merchant to submit merchant's specific data. |
||
|
userDefined3 |
C 150 |
O |
For merchant to submit merchant's specific data. |
||
|
userDefined4 |
C 150 |
O |
For merchant to submit merchant's specific data. |
||
|
userDefined5 |
C 150 |
O |
For merchant to submit merchant's specific data. |
||
|
acquirerReferenceNo |
C 50 |
O |
Transaction reference number provided by acquirer. |
||
|
acquirerMerchantId |
C 50 |
O |
MID used for authorization to the acquirer (only for MID(s) belong to merchant can enable this option) |
||
|
idempotencyID |
C 100 |
O |
Unique idempotency ID |
||
|
paymentScheme |
C 30 |
C |
Payment Scheme Refer to Payment Scheme / Process by List |
||
|
idempotencyID |
C 100 |
O |
Idempotency Number. |
||
|
loyaltyPoints |
Array | O | Loyalty info | ||
| paymentScheme | C 20 | M | Provider ID | ||
| redeemAmount | D 12,5 | M | Total Redeem Amount | ||
| rewards | Array | M | Reward info | ||
| type | C 1 | M | Loyalty Type, "P" (POINTS) / "V" (Voucher) | ||
| name | C 255 | M | Provider Name | ||
| quantity | D 12,5 | M | Points quantity | ||
| price | D 12,5 | M | Price per quantity | ||
| amount | D 12,5 | M | Amount | ||
| totalPrice | D 12,5 | M | Total price | ||
| totalAmount | D 12,5 | M | Total amount | ||
| paymentID | C 255 | M | paymentID for referencing this transaction for future payment such as "MIT" e.g ccpp_12345678 | ||
| schemePaymentID | C 255 | C | Value is returned if scheme payment ID is available from acquirer | ||
| acquirerResponseCode | N 2 | O | ISO 8583's Response Code. The value is Available if Acquirer returns ISO 8583's Response Code | ||
|
respCode |
C 4 |
M |
Response Code Refer to Response Code List |
||
|
respDesc |
C 255 |
M |
Response Code Description |
||
Event types
The notification system uses an event-driven architecture. Route your business logic based on the category and event fields.
| event | Description | When it fires |
|---|---|---|
SALE | Purchase transaction completed | After a customer taps their card and the payment is processed |
AUTH | Pre-authorisation hold placed | After a pre-auth is successfully placed on the card |
CAPTURE | Authorisation captured | After a prior AUTH is captured (partial or full) |
VOID | Authorisation voided | After a prior AUTH is cancelled before capture |
REFUND | Refund processed | After a refund is issued against a completed SALE or CAPTURE |
Security
JWT signature verification
The payload field is a signed JWT. Before processing any notification:
- Verify the JWT signature using the shared secret or public key provided during onboarding.
- Validate the claims — confirm the
merchantIDmatches your merchant ID. - Check the
versionfield — handle or reject unknown versions as appropriate.
Never trust a notification whose JWT signature cannot be verified. An unverified notification may have been tampered with in transit.
Handling the notification
Recommended processing flow
- Receive — Accept the POST request and read the JSON body.
- Verify — Validate the JWT signature on
payload. Reject if invalid. - Update — Update your order management, ledger, or ERP system with the transaction result.
- Respond — Return HTTP
200 OKwith an empty body.
// Successful response — your server returns:
HTTP/1.1 200 OK
Content-Type: application/json
{}Sample notifications
Successful SALE
{
"category": "PAYMENT",
"event": "SALE",
"version": "4.3",
"payload": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjaGFudElEIjoiSlQwNCIsImludm9pY2VObyI6IjI4MDUyMDA3NTkyMSIsImNhcmRObyI6IjQxMTExMVhYWFhYWDExMTEiLCJhbW91bnQiOiIyMzAuODciLCJjdXJyZW5jeUNvZGUiOiJUSEIiLCJ0cmFuUmVmIjoiMjg2ODgyMSIsInJlZmVyZW5jZU5vIjoiMjc4NTcwMyIsImFwcHJvdmFsQ29kZSI6IjUzMTQ4NCIsImVjaSI6IjA1IiwidHJhbnNhY3Rpb25EYXRlVGltZSI6IjIwMjAwNTI4MDgwNTA4IiwicmVzcENvZGUiOiIwMDAwIiwicmVzcERlc2MiOiJTdWNjZXNzIn0.QdjSI_dUbiRularwEIFuYROE_svc3Xkm-t58X-VnPxI",
"invoiceNo": "M1790593277278339073",
"respCode": "0000",
"respDesc": "Success"
}Decoded payload:
{
"merchantID": "JT04",
"invoiceNo": "280520075921",
"cardNo": "411111XXXXXX1111",
"amount": "230.87",
"currencyCode": "THB",
"tranRef": "2868821",
"referenceNo": "2785703",
"approvalCode": "531484",
"eci": "05",
"transactionDateTime": "20200528080508",
"respCode": "0000",
"respDesc": "Success"
}Failed SALE
{
"category": "PAYMENT",
"event": "SALE",
"version": "4.3",
"payload": "eyJhbGciOiJIUzI1NiJ9.eyJtZXJjaGFudElEIjoiSlQwNCIsImludm9pY2VObyI6Ik0xNzkwNTkzMjc3Mjc4MzM5MDc0IiwiY2FyZE5vIjoiNDExMTExWFhYWFhYMTExMSIsImFtb3VudCI6IjUwLjAwIiwiY3VycmVuY3lDb2RlIjoiVEhCIiwidHJhblJlZiI6IjI4Njg4MjIiLCJyZWZlcmVuY2VObyI6IjI3ODU3MDQiLCJhcHByb3ZhbENvZGUiOiIiLCJlY2kiOiIiLCJ0cmFuc2FjdGlvbkRhdGVUaW1lIjoiMjAyMDA1MjgwODA1MDgiLCJyZXNwQ29kZSI6IjEwMDEiLCJyZXNwRGVzYyI6IkRlY2xpbmVkIn0.signature",
"invoiceNo": "M1790593277278339074",
"respCode": "1001",
"respDesc": "Declined"
}Note: For failed transactions,
approvalCodeandeciare empty strings. Always checkrespCodebefore updating your system to a successful state.
VOID
{
"category": "PAYMENT",
"event": "VOID",
"version": "4.3",
"payload": "eyJhbGciOiJIUzI1NiJ9.eyJtZXJjaGFudElEIjoiSlQwNCIsImludm9pY2VObyI6Ik0xNzkwNTkzMjc3Mjc4MzM5MDc1IiwiaW52b2ljZU5vIjoiTTE3OTA1OTMyNzcyNzgzMzkwNzUiLCJjYXJkTm8iOiI0MTExMTFYWFhYWFgxMTExIiwiYW1vdW50IjoiMTAwLjAwIiwiY3VycmVuY3lDb2RlIjoiVEhCIiwidHJhblJlZiI6IjI4Njg4MjMiLCJyZWZlcmVuY2VObyI6IjI3ODU3MDUiLCJhcHByb3ZhbENvZGUiOiI1MzE0ODUiLCJlY2kiOiIwNSIsInRyYW5zYWN0aW9uRGF0ZVRpbWUiOiIyMDIwMDUyODA4MDUwOCIsInJlc3BDb2RlIjoiMDAwMCIsInJlc3BEZXNjIjoiVm9pZCBzdWNjZXNzZnVsIn0.signature",
"invoiceNo": "M1790593277278339075",
"respCode": "0000",
"respDesc": "Void successful"
}Note: VOID and REFUND notifications reference the original transaction. Match these against the original
tranRefstored in your system.
Response codes
Common response codes returned in the notification. For the complete list, see Payment Response Codes.
| Code | Description | Recommended action |
|---|---|---|
0000 |
Successful | Transaction approved. Update order to confirmed/paid. |
0001 |
Transaction is pending | Transaction is still processing. Wait for a subsequent notification before fulfilling the order. |
0003 |
Transaction is cancelled | Transaction was cancelled. Do not fulfil the order. |
0999 |
System error | Internal processing error. Use the Inquiry API to verify the final status. |
2002 |
Transaction not found | Transaction reference cannot be found. Verify the invoiceNo and retry. |
4005 |
Do not honor | Issuer declined without a specific reason. Prompt customer to contact their bank. |
4051 |
Insufficient funds | Cardholder has insufficient balance. Prompt customer to use another card. |
4054 |
Expired card | Card has expired. Prompt customer to use another card. |
Testing
Use the 2C2P Sandbox environment to test your notification handler before going live.
- Configure your sandbox notification endpoint URL with the 2C2P integration team.
- Process test transactions through your SoftPOS integration.
- Verify that your server receives, verifies, and acknowledges each notification.
- Test failure scenarios: declined transactions, void, and refund notifications.
Updated about 2 hours ago
