Test mode values
Values that make test mode succeed, fail or wait, endpoint by endpoint, with the steps to try each one.
Test mode lets you build your integration without touching a bank or moving money. Use your test API key: Acme checks each request, then simulates the bank. The values below make the simulated bank fail, wait or return a specific answer.
Each API reference page with test values links to its section here.
Payments
| Endpoint | Field | Value | What happens |
|---|---|---|---|
| Create a Payment | receiver.bankAccountNumber | 000000000, 000000001 | The payment fails at once. |
| Create a Batch Payment | receiver.bankAccountNumber | 000000000, 000000001 | That payment fails. |
| Create a Batch Payment | receiver.bankAccountNumber | 000000002 | The whole batch is rejected. |
Some banks behave differently in test mode. The steps, example payloads and a table by bank are in:
Direct debit authorizations
Singapore
A successful authorization returns null for payerIdType and payerIdHash. To get mock payer
identification instead:
Create the authorization with billReferenceNumber S1234567D (exact match: s1234567d does not work) and a
payerSwiftBic from List Direct Debit Banks.
{
"billReferenceNumber": "S1234567D",
"payerSwiftBic": "DBSSSGSGXXX",
"payerSegment": "RETAIL",
"payerName": "Richard Hendricks",
"precheckMaxAmount": 100000,
"precheckCurrency": "SGD",
"endDate": "2042-04-24",
"returnUrl": "https://example.com/return"
}Open the authorization page in the response and choose the success scenario.
Get the authorization. It is SUCCEEDED with these mock values:
| Field | Value |
|---|---|
payerIdType | NRIC |
payerIdHash | 3578b829767388a631b999b7049e830827b3e99b7504581bcfefa72def689658 |
The hash is the hex-encoded SHA-256 of S1234567D. It is a fixed value, not derived from a real ID.
Hong Kong, your account at HSBC
When your collection account is at HSBC Hong Kong, test authorizations go to a simulated HSBC that follows HSBC's own rules. No SMS is sent.
Create an authorization for a payer who banks with HSBC (payerBankCode 004). Send
payerMobileNumber: HSBC requires it.
{
"billReferenceNumber": "A0012334455",
"payerName": "Wong Ka Ming",
"payerIdType": "HKID",
"payerIdNumber": "A1234563",
"payerMobileNumber": "+85291231234",
"payerBankCode": "004",
"payerAccountNumber": "511123456888",
"precheckMaxAmount": 1000000,
"precheckCurrency": "HKD"
}The response is REQUIRES_AUTHORIZATION with an otp object.
Confirm the OTP. The code is always 123456.
{ "otpId": "<otp.id from the response>", "otpCode": "123456" }The response is SUBMITTED.
Wait for activation. HSBC activates it 30 to 60 seconds later, and Acme checks every 3 seconds after
a confirmation. Expect SUCCEEDED and the direct-debit-authorizations.succeeded webhook within
about a minute.
A payer at any other bank gets no OTP. The authorization is SUBMITTED, and becomes SUCCEEDED with
the webhook about 90 seconds after you create it. ultimatePayerName Msg NORMAL004000001, HSBC's
own test value, does the same.
Payer account numbers that fail
For a payer at HSBC (payerBankCode 004), put one of these in payerAccountNumber. The
authorization is FAILED with this reason, and Acme sends direct-debit-authorizations.failed. 002039147001, 002027522001 and
999999999999 are HSBC's own test accounts, so they also work in HSBC's test environment.
payerAccountNumber | Failure reason | HSBC code | Why |
|---|---|---|---|
900000001005 | PAYER_ACCOUNT_NAME_AND_ID_NOT_MATCHED | MPP01005 | Name and ID do not match |
900000001006 | PAYER_MOBILE_NUMBER_INVALID | MPP01006 | Mobile number does not match |
900000001007 | PAYER_ACCOUNT_NAME_NOT_MATCHED | MPP01007 | Name does not match |
002039147001 | PAYER_MOBILE_NUMBER_INVALID | MPP01008 | The bank holds no mobile number |
002027522001 | PAYER_ACCOUNT_TYPE_NOT_SUPPORTED | MPP03001 | Not a personal account |
900000000001 | PAYER_ACCOUNT_NOT_FOUND | MFISAC01 | No such account |
999999999999 | OTHERS | MPP09996 | Bank maintenance: create a new one to retry |
900000001009 | PAYER_MOBILE_NUMBER_INVALID | RJCT | The mobile number HSBC holds is not numeric |
OTP rules
| What you do | Error from /otp-confirmation or /otp-regeneration |
|---|---|
Send a wrong code. attemptsRemaining counts down from 3, codes sent at the same time included. | OTP_INCORRECT |
| Try a 4th time after 3 wrong codes, even with the right code. | OTP_ATTEMPTS_EXHAUSTED: regenerate the OTP |
| Send a code 100 seconds or more after the OTP was issued. It uses up an attempt. | OTP_EXPIRED: regenerate the OTP |
Send an otpId that is not the latest otp.id. | OTP_NOT_CURRENT |
Confirm before the authorization has an otp. | OTP_NOT_CURRENT: regenerate the OTP first |
| Ask for a 3rd OTP on the same Hong Kong day, the first one included. | OTP_DAILY_LIMIT_REACHED |
| Regenerate while another regeneration is still with the bank. | CONFLICT (HTTP 409): use the otp the first one returns |
An authorization whose OTP is never confirmed becomes FAILED with PAYER_AUTHORIZATION_TIMEOUT, and
the direct-debit-authorizations.failed webhook, after 7 days, as HSBC deletes it.
Payer names that change the outcome
Put one of these in ultimatePayerName. Each FAILED below also sends
direct-debit-authorizations.failed.
ultimatePayerName | What happens |
|---|---|
Msg EDDA00010001 | A payer at another bank: their bank rejects it. FAILED with PAYER_AUTHORIZATION_FAILED. |
Acme TEST CREATE TIMEOUT | HSBC's answer is lost: SUBMITTED with no otp. About 30 seconds later an HSBC payer is REQUIRES_AUTHORIZATION with no otp: call /otp-regeneration (it counts as their 2nd OTP that day, and its mobileNumber is empty). |
Acme TEST CREATE LOST | HSBC never received it: SUBMITTED, then FAILED with OTHERS about 15 minutes later. The billReferenceNumber can then be used again. |
Acme TEST RATE LIMITED | HSBC turns it away: FAILED with OTHERS. Create a new one. |
Acme TEST PENDING | A payer at another bank: their bank never answers, so it stays SUBMITTED. |
Acme TEST CONFIRM UNAVAILABLE | The first /otp-confirmation gets RETRYABLE_UPSTREAM_ERROR (HTTP 503) and uses an attempt. Send the code again. |
Acme TEST REGENERATE UNAVAILABLE | /otp-regeneration within 30 seconds of the last OTP gets RETRYABLE_UPSTREAM_ERROR (HTTP 503). Later ones work. |
Acme TEST CANCELLED, Acme TEST EXPIRED, Acme TEST DELETED | The authorization succeeds, then HSBC ends the mandate a minute later: CANCELED and the direct-debit-authorizations.canceled webhook within about 10 minutes. Live, HSBC reports this once a day. |
Acme TEST SUSPENDED, Acme TEST DORMANT | The authorization succeeds, then the mandate is suspended or dormant at HSBC. It stays SUCCEEDED. |
Hong Kong, your account at Standard Chartered
When your collection account is at Standard Chartered Hong Kong:
payerAccountNumber | What happens |
|---|---|
000000000 | The authorization is FAILED. |
| Any other number | The authorization is SUCCEEDED at once. |
Direct debit payments
| Endpoint | Field | Value | What happens |
|---|---|---|---|
| Create a Direct Debit Collection | customerReference | fail | FAILED with resultCode OTHERS. |
| Create a Direct Debit Collection | customerReference | pending | SUBMITTED, then SUCCEEDED at Acme's next status check. |
| Create a Direct Debit Collection | customerReference | Anything else | SUCCEEDED at once. |
| Create a Batch Direct Debit Collection | payments[].customerReference | FAIL | That payment fails. |
| Create a Batch Direct Debit Collection | payments[].customerReference | FAIL-BATCH | The whole batch is rejected, and every payment in it fails. |
The values are exact and case-sensitive: fail and pending for a single collection, FAIL and
FAIL-BATCH in a batch.
{
"type": "FAST",
"amount": 4200,
"currency": "SGD",
"directDebitAuthorizationId": "dda_0H3BQMGGRTFXT",
"customerReference": "fail"
}Hosted payments
Send hostedPaymentMethodId with Create a Hosted Payment.
hostedPaymentMethodId | method | What happens |
|---|---|---|
hpm_TESTMODESUCCEEDED | Any | SUCCEEDED. |
hpm_TESTMODEFAILED_PAYLAHWALLETDELINKED | PAYLAH | FAILED: the customer unlinked their PayLah! wallet. |
hpm_TESTMODEPENDING_INSUFFICIENTFUNDSPENDINGTOPUP | PAYLAH | PENDING: the wallet has too little balance, and the customer was asked to top up. |
Any other id, or a PayLah! id with another method | Any | FAILED. |
{
"amount": 4242,
"currency": "SGD",
"channel": "WEB_BROWSER_DESKTOP",
"method": "PAYLAH",
"hostedPaymentMethodId": "hpm_TESTMODESUCCEEDED"
}Tracked payment QR codes
Create a tracked QR code always answers PENDING.
The payment then moves on by these values, checked in this order:
| Field | Value | What happens |
|---|---|---|
proxyValue, with proxyType UEN | 000000001 | SUCCEEDED |
proxyValue, with proxyType UEN | 000000002 | FAILED |
amount | 117 | SUCCEEDED |
amount | 72 | FAILED |
Any other code stays PENDING until you call
Perform a direct lookup of a tracked QR code, which marks it
SUCCEEDED.
Refunds
Send one of these as transactionId with Create a Refund.
transactionId | What happens |
|---|---|
txn_SuccessfulRefund | PENDING, then SUCCEEDED about 5 seconds later, with refunds.succeeded. |
txn_FailedRefund | PENDING, then FAILED about 5 seconds later, with refunds.failed. |
txn_InvalidTransaction | 400 INVALID_OPERATION: Transaction cannot be refunded. |
txn_AlreadyRefunded | 400 INVALID_OPERATION: Transaction has been fully refunded. |
txn_RejectPartialRefund | 400 INVALID_OPERATION: Partial refund is not supported. |
txn_RejectOverRefund | 400 INVALID_OPERATION: Requested refund amount exceeds transaction's refundable amount. |
txn_NoLongerRefundable | 400 INVALID_OPERATION: Transaction is no longer refundable. |
| Any other id | 400 INVALID_REQUEST_PARAMETER: Transaction not found. |
Bank account verifications
Send one of these as accountNumber with
Verify identity of bank account holder.
accountNumber | What happens |
|---|---|
4242424200 or 545454500 | Verified. |
4242424291 or 545454591 | Not verified: INVALID_IDENTITY_NUMBER. |
4242424292 or 545454592 | Not verified: IDENTITY_NOT_FOUND. |
4242424293 or 545454593 | Not verified: IDENTITY_MISMATCH. |
4242424294 or 545454594 | Not verified: ACCOUNT_CLOSED. |
| Any other number | Not verified: OTHERS. |
Payment proxy lookup
With Look up a payment proxy address, every proxy is found except
these, which answer PROXY_NOT_REGISTERED:
| Scheme | Proxy type | Value |
|---|---|---|
| PayNow (Singapore) | UEN | 201912345NABC |
| PayNow (Singapore) | MOBILE | +6511111111 |
| DuitNow (Malaysia) | BUSINESS_REG | 11111A |
| DuitNow (Malaysia) | MOBILE | 60121111111 |
Foreign exchange
In test mode, Look Up Forex Rates and Create a Forex Booking use fixed sample rates, not live market rates. Do not use them to check your pricing.