BillPayment
POST
https://test.api.neotek.sa/b2b-unified/v1/sadad/paymentSandbox URL · in Production call https://api.neotek.sa
Pays the bill. The payment settles within the call, so the response comes back PAYMENT_COMPLETED and there is nothing to poll afterwards.
Body:
| Parameter | Required | Description |
|---|---|---|
bankCode | Required | which bank makes the payment: RJHISARI or ARNBSARI |
billerCode | Required | the biller, as a 3-digit zero-padded code |
subscriberNumber | Required | the account with that biller, up to 30 characters |
amount | Required | decimal with 2 places. See the warning below on when it is used |
debitAccountIban | Required | the account the money leaves, SA plus 22 digits |
transactionReference | Optional | your own reference, up to 16 characters. Generated if omitted |
payExactDue | Optional | boolean, defaulting to true |
amount is ignored by default. payExactDue defaults to true, which tells the bank to pay whatever is actually due rather than the figure you sent. If the bill changed between your inquiry and your payment, you are debited the new amount. Reconcile against paidAmount in the response, never against the amount you requested.
Headers:
| Parameter | Required | Description |
|---|---|---|
authorization | Required | Bearer <ACCESS_TOKEN> |
content-type | Required | application/json |
cURL
curl -X POST 'https://test.api.neotek.sa/b2b-unified/v1/sadad/payment' \ --header 'authorization: Bearer <ACCESS_TOKEN>' \ --header 'content-type: application/json' \ --data '{ "bankCode": "ARNBSARI", "billerCode": "002", "subscriberNumber": "4210056076", "amount": "2708.20", "debitAccountIban": "SA1030000012345678901004" }'Response — paidAmount is what was actually debited
JSON
{ "success": true, "code": "PAYMENT_COMPLETED", "message": "SADAD payment completed successfully", "billerCode": "002", "subscriberNumber": "4210056076", "paidAmount": "2708.20", "paidDate": "2026-05-01", "sadadReference": "DE1234567890", "transactionReference": "a1b2c3d4e5f6g7h8", "paymentStatus": "PAYMENT_STATUS_COMPLETED"}Errors — each failure carries an error category and a specific code
| Status | Codes | Cause |
|---|---|---|
400 ERROR_CATEGORY_VALIDATION_FAILED | INVALID_ACCOUNT, INVALID_AMOUNT, INVALID_BANK_CODE, ACCOUNT_NOT_FOUND | Unknown biller code, bad subscriber number, malformed IBAN |
401 ERROR_CATEGORY_AUTH_FAILED | AUTH_FAILED, CREDENTIALS_NOT_FOUND | Token expired, or missing ANB SADAD account configuration |
404 ERROR_CATEGORY_NOT_FOUND | NOT_FOUND | No bill for that biller and subscriber pair |
409 ERROR_CATEGORY_DUPLICATE | DUPLICATE_TRANSACTION | You reused a transactionReference |
422 ERROR_CATEGORY_BANK_REJECTED | INSUFFICIENT_FUNDS, ACCOUNT_BLOCKED, PAYMENT_NOT_ALLOWED | The bank declined it |
503 ERROR_CATEGORY_TEMPORARY_FAILURE | BANK_UNAVAILABLE, NETWORK_TIMEOUT | Retry with backoff |