Skip to content

Transactions

Request

POST https://api-dev.spay.ng/api/v1/transactions/enquiry
Authorization: Bearer <access-token>
Accept: application/json
Content-Type: application/json
{
"sourceAccountNumber": "8880000001",
"destinationBankCode": "000013",
"destinationAccountNumber": "0123456789"
}
curl
curl -X POST 'https://api-dev.spay.ng/api/v1/transactions/enquiry' \
-H "Authorization: Bearer $SPAY_ACCESS_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"sourceAccountNumber": "8880000001",
"destinationBankCode": "000013",
"destinationAccountNumber": "0123456789"
}'

Request fields

FieldTypeRequiredDescription
sourceAccountNumberstring, 10 digitsYesYour account the transfer would be sent from. Not one of yours returns 404, code 25.
destinationBankCodestring, 3 to 6 digitsYesThe destination institution’s institutionCode.
destinationAccountNumberstring, 10 digitsYesThe account to look up. Not found returns 404, code 25.

Response: 200 OK

{
"sourceAccountNumber": "8880000001",
"destinationBankCode": "000013",
"destinationAccountNumber": "0123456789",
"destinationAccountName": "Example Beneficiary",
"destinationBankName": "Example Bank"
}

Response fields

FieldTypeDescription
sourceAccountNumberstring, 10 digitsAs sent.
destinationBankCodestringAs sent.
destinationAccountNumberstring, 10 digitsAs sent.
destinationAccountNamestringThe destination account’s name.
destinationBankNamestring or nullThe destination institution’s name.

Errors

HTTP statusBody
400{"error":{"code":"30","message":"Invalid request"}}
400{"error":{"code":"06","message":"Request refused"}}
401{"error":{"code":"63","message":"Missing, invalid or expired access token"}}
403{"error":{"code":"63","message":"Operation not permitted"}}
404{"error":{"code":"25","message":"Resource not found"}}
503{"error":{"code":"91","message":"Service unavailable"}}

Request

POST https://api-dev.spay.ng/api/v1/transactions
Authorization: Bearer <access-token>
Accept: application/json
Content-Type: application/json
{
"sourceAccountNumber": "8880000001",
"destinationBankCode": "000013",
"destinationAccountNumber": "0123456789",
"amount": 1000.0,
"narration": "POS payment",
"reference": "pay-pos-0001"
}
curl
curl -X POST 'https://api-dev.spay.ng/api/v1/transactions' \
-H "Authorization: Bearer $SPAY_ACCESS_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"sourceAccountNumber": "8880000001",
"destinationBankCode": "000013",
"destinationAccountNumber": "0123456789",
"amount": 1000.0,
"narration": "POS payment",
"reference": "pay-pos-0001"
}'

Request fields

FieldTypeRequiredDescription
sourceAccountNumberstring, 10 digitsYesYour account to debit.
destinationBankCodestring, 3 to 6 digitsYesThe destination institution’s institutionCode.
destinationAccountNumberstring, 10 digits, not the source accountYesThe account to pay.
amountnumber, naira, from 0.01, at most 2 decimal placesYesThe amount to send. More than 2 decimal places returns 400, code 30.
narrationstring, 1 to 100 charactersYesThe transfer’s narration.
referencestring, 1 to 100 characters, not starting with REVERSED:YesYour unique reference for this transfer. Reuse it on every retry and look the transfer up by it.

Response: 202 Accepted

{
"reference": "pay-pos-0001",
"originalReference": null,
"ownerAccountNumber": "8880000001",
"type": "INTERBANK_TRANSFER",
"mode": "DEBIT",
"status": "PENDING",
"reviewRequired": false,
"amount": 1000.0,
"feeAmount": 1.25,
"currency": "NGN",
"source": {
"accountNumber": "8880000001",
"accountName": "Adunni Foods"
},
"beneficiary": {
"accountNumber": "0123456789",
"accountName": "Example Beneficiary",
"institutionCode": "000013",
"institutionName": "Example Bank"
},
"narration": "POS payment",
"failureReason": null,
"transactionDate": "2026-10-25T09:15:00+01:00",
"updatedAt": "2026-10-25T09:15:00+01:00"
}

Response: 200 OK with the same body when the transfer is final within the call, with status SUCCESSFUL or FAILED.

Response fields

FieldTypeDescription
referencestringYour reference.
originalReferencenullAlways null for a transfer.
ownerAccountNumberstring, 10 digitsThe source account.
typeenum: INTRABANK_TRANSFER, INTERBANK_TRANSFERINTRABANK_TRANSFER when the destination is a Spay account, otherwise INTERBANK_TRANSFER.
modestring, DEBITMoney leaves the source account.
statusenum: PENDING, SUCCESSFUL, FAILEDThe transfer’s status.
reviewRequiredbooleantrue while Spay establishes the outcome.
amountnumber, naira, at most 2 decimal placesThe amount sent.
feeAmountnumber, naira, at most 2 decimal placesThe fee charged on the transfer, net of any refund. 0 when no fee was charged.
currencystring, NGNThe currency.
source.accountNumberstring, 10 digitsThe source account.
source.accountNamestring or nullThe source account’s name.
beneficiary.accountNumberstring, 10 digitsThe destination account.
beneficiary.accountNamestring or nullThe destination account’s name.
beneficiary.institutionCodestring, omitted when unknownThe destination institution’s code.
beneficiary.institutionNamestring, omitted when unknownThe destination institution’s name.
narrationstringYour narration.
failureReasonenum: INSUFFICIENT_FUNDS, SOURCE_ACCOUNT_UNAVAILABLE, BENEFICIARY_UNAVAILABLE, CANCELLED, PROCESSING_ERROR, or nullWhy a FAILED transfer failed; null otherwise.
transactionDatetimestampWhen the transfer was made.
updatedAttimestampWhen the transfer last changed.
  • feeAmount is charged in addition to amount.
  • Over the single or daily transfer limit returns 400, code 61. Transfers between a customer’s own accounts at Spay don’t count against limits.
  • A refusal made before the transfer is recorded leaves the reference free to reuse: 400 with code 30, 61, 25 (beneficiary not found at enquiry) or 06, and 404 (source account).
  • 409, code 94: the reference already belongs to a transfer. Read Get transaction status by reference and follow its status.
  • Once the transfer is recorded, a refusal answers 400 with code 51, 57, 07 or 96, and the transfer is recorded as FAILED. The reference is used, and Get transaction status returns the transfer.
  • 503 means Spay couldn’t complete the call. The transfer may still have been recorded as PENDING.
  • When the call gets no response or a 503, read Get transaction status by reference. A 404 means the transfer wasn’t recorded: send it again with the same reference. Otherwise follow its status. Never retry with a new reference.
  • When reviewRequired is true, the outcome is being established by Spay and status stays PENDING. Wait for the webhook, and don’t retry.
  • References are unique across all your API clients, per resource (an opening reference and a transfer reference don’t collide), and they are kept forever.

Errors

HTTP statusBody
400{"error":{"code":"30","message":"Invalid request"}}
400{"error":{"code":"61","message":"Limit exceeded"}}
400{"error":{"code":"25","message":"Resource not found"}}
400{"error":{"code":"06","message":"Request refused"}}
400{"error":{"code":"51","message":"Insufficient funds"}}
400{"error":{"code":"57","message":"Source account unavailable"}}
400{"error":{"code":"07","message":"Beneficiary account unavailable"}}
400{"error":{"code":"96","message":"Processing error"}}
401{"error":{"code":"63","message":"Missing, invalid or expired access token"}}
403{"error":{"code":"63","message":"Operation not permitted"}}
404{"error":{"code":"25","message":"Resource not found"}}
409{"error":{"code":"94","message":"Reference has already been used; query the existing operation"}}
503{"error":{"code":"91","message":"Service unavailable"}}

Request

GET https://api-dev.spay.ng/api/v1/transactions/pay-pos-0001
Authorization: Bearer <access-token>
Accept: application/json
curl
curl 'https://api-dev.spay.ng/api/v1/transactions/pay-pos-0001' \
-H "Authorization: Bearer $SPAY_ACCESS_TOKEN" \
-H "Accept: application/json"

No request body.

Request fields

FieldTypeRequiredDescription
reference (path)stringYesThe transaction’s reference: yours for a transfer you made.

Response: 200 OK

{
"reference": "pay-pos-0001",
"originalReference": null,
"ownerAccountNumber": "8880000001",
"type": "INTERBANK_TRANSFER",
"mode": "DEBIT",
"status": "SUCCESSFUL",
"reviewRequired": false,
"amount": 1000.0,
"feeAmount": 1.25,
"currency": "NGN",
"source": {
"accountNumber": "8880000001",
"accountName": "Adunni Foods"
},
"beneficiary": {
"accountNumber": "0123456789",
"accountName": "Example Beneficiary",
"institutionCode": "000013",
"institutionName": "Example Bank"
},
"narration": "POS payment",
"failureReason": null,
"transactionDate": "2026-10-25T09:15:00+01:00",
"updatedAt": "2026-10-25T09:15:30+01:00"
}

Response fields

FieldTypeDescription
referencestringThe transaction’s reference.
originalReferencestring or nullSet on a reversal: the reference of the transaction it reverses.
ownerAccountNumberstring, 10 digitsThe account the transaction belongs to.
typeenum: INTERBANK_TRANSFER, INTRABANK_TRANSFER, BILL_PAYMENT_DEBIT, BILL_PAYMENT_REVERSALWhat kind of transaction it is.
modeenum: DEBIT, CREDITWhether money left or reached the account.
statusenum: PENDING, SUCCESSFUL, FAILED, REVERSEDThe transaction’s status.
reviewRequiredbooleantrue while Spay establishes the outcome of a PENDING transaction.
amountnumber, naira, at most 2 decimal placesThe amount.
feeAmountnumber, naira, at most 2 decimal placesThe fee charged on the transaction, net of any refund. 0 when no fee was charged.
currencystring, NGNThe currency.
source.accountNumberstring or nullThe account the money came from.
source.accountNamestring or nullThat account’s name.
source.institutionCodestring, omitted for the owner accountThe sending institution’s code.
source.institutionNamestring, omitted for the owner accountThe sending institution’s name.
beneficiary.accountNumberstring or nullThe account the money went to.
beneficiary.accountNamestring or nullThat account’s name.
beneficiary.institutionCodestring, omitted for the owner accountThe receiving institution’s code.
beneficiary.institutionNamestring, omitted for the owner accountThe receiving institution’s name.
narrationstring, may be emptyThe transaction’s narration.
failureReasonenum: INSUFFICIENT_FUNDS, SOURCE_ACCOUNT_UNAVAILABLE, BENEFICIARY_UNAVAILABLE, CANCELLED, PROCESSING_ERROR, or nullWhy a FAILED transaction failed; null otherwise.
transactionDatetimestampWhen the transaction happened.
updatedAttimestampWhen the transaction last changed.

Errors

HTTP statusBody
401{"error":{"code":"63","message":"Missing, invalid or expired access token"}}
403{"error":{"code":"63","message":"Operation not permitted"}}
404{"error":{"code":"25","message":"Resource not found"}}
503{"error":{"code":"91","message":"Service unavailable"}}