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

EndpointFieldValueWhat happens
Create a Paymentreceiver.bankAccountNumber000000000, 000000001The payment fails at once.
Create a Batch Paymentreceiver.bankAccountNumber000000000, 000000001That payment fails.
Create a Batch Paymentreceiver.bankAccountNumber000000002The 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.

POST /v1/direct-debit-authorizations
{
  "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:

FieldValue
payerIdTypeNRIC
payerIdHash3578b829767388a631b999b7049e830827b3e99b7504581bcfefa72def689658

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.

POST /v1/direct-debit-authorizations
{
  "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.

POST /v1/direct-debit-authorizations/{id}/otp-confirmation
{ "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.

payerAccountNumberFailure reasonHSBC codeWhy
900000001005PAYER_ACCOUNT_NAME_AND_ID_NOT_MATCHEDMPP01005Name and ID do not match
900000001006PAYER_MOBILE_NUMBER_INVALIDMPP01006Mobile number does not match
900000001007PAYER_ACCOUNT_NAME_NOT_MATCHEDMPP01007Name does not match
002039147001PAYER_MOBILE_NUMBER_INVALIDMPP01008The bank holds no mobile number
002027522001PAYER_ACCOUNT_TYPE_NOT_SUPPORTEDMPP03001Not a personal account
900000000001PAYER_ACCOUNT_NOT_FOUNDMFISAC01No such account
999999999999OTHERSMPP09996Bank maintenance: create a new one to retry
900000001009PAYER_MOBILE_NUMBER_INVALIDRJCTThe mobile number HSBC holds is not numeric

OTP rules

What you doError 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.

ultimatePayerNameWhat happens
Msg EDDA00010001A payer at another bank: their bank rejects it. FAILED with PAYER_AUTHORIZATION_FAILED.
Acme TEST CREATE TIMEOUTHSBC'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 LOSTHSBC never received it: SUBMITTED, then FAILED with OTHERS about 15 minutes later. The billReferenceNumber can then be used again.
Acme TEST RATE LIMITEDHSBC turns it away: FAILED with OTHERS. Create a new one.
Acme TEST PENDINGA payer at another bank: their bank never answers, so it stays SUBMITTED.
Acme TEST CONFIRM UNAVAILABLEThe 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 DELETEDThe 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 DORMANTThe 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:

payerAccountNumberWhat happens
000000000The authorization is FAILED.
Any other numberThe authorization is SUCCEEDED at once.

Direct debit payments

EndpointFieldValueWhat happens
Create a Direct Debit CollectioncustomerReferencefailFAILED with resultCode OTHERS.
Create a Direct Debit CollectioncustomerReferencependingSUBMITTED, then SUCCEEDED at Acme's next status check.
Create a Direct Debit CollectioncustomerReferenceAnything elseSUCCEEDED at once.
Create a Batch Direct Debit Collectionpayments[].customerReferenceFAILThat payment fails.
Create a Batch Direct Debit Collectionpayments[].customerReferenceFAIL-BATCHThe 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.

POST /v1/direct-debit-payments
{
  "type": "FAST",
  "amount": 4200,
  "currency": "SGD",
  "directDebitAuthorizationId": "dda_0H3BQMGGRTFXT",
  "customerReference": "fail"
}

Hosted payments

Send hostedPaymentMethodId with Create a Hosted Payment.

hostedPaymentMethodIdmethodWhat happens
hpm_TESTMODESUCCEEDEDAnySUCCEEDED.
hpm_TESTMODEFAILED_PAYLAHWALLETDELINKEDPAYLAHFAILED: the customer unlinked their PayLah! wallet.
hpm_TESTMODEPENDING_INSUFFICIENTFUNDSPENDINGTOPUPPAYLAHPENDING: the wallet has too little balance, and the customer was asked to top up.
Any other id, or a PayLah! id with another methodAnyFAILED.
POST /v1/hosted-payments
{
  "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:

FieldValueWhat happens
proxyValue, with proxyType UEN000000001SUCCEEDED
proxyValue, with proxyType UEN000000002FAILED
amount117SUCCEEDED
amount72FAILED

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.

transactionIdWhat happens
txn_SuccessfulRefundPENDING, then SUCCEEDED about 5 seconds later, with refunds.succeeded.
txn_FailedRefundPENDING, then FAILED about 5 seconds later, with refunds.failed.
txn_InvalidTransaction400 INVALID_OPERATION: Transaction cannot be refunded.
txn_AlreadyRefunded400 INVALID_OPERATION: Transaction has been fully refunded.
txn_RejectPartialRefund400 INVALID_OPERATION: Partial refund is not supported.
txn_RejectOverRefund400 INVALID_OPERATION: Requested refund amount exceeds transaction's refundable amount.
txn_NoLongerRefundable400 INVALID_OPERATION: Transaction is no longer refundable.
Any other id400 INVALID_REQUEST_PARAMETER: Transaction not found.

Bank account verifications

Send one of these as accountNumber with Verify identity of bank account holder.

accountNumberWhat happens
4242424200 or 545454500Verified.
4242424291 or 545454591Not verified: INVALID_IDENTITY_NUMBER.
4242424292 or 545454592Not verified: IDENTITY_NOT_FOUND.
4242424293 or 545454593Not verified: IDENTITY_MISMATCH.
4242424294 or 545454594Not verified: ACCOUNT_CLOSED.
Any other numberNot verified: OTHERS.

Payment proxy lookup

With Look up a payment proxy address, every proxy is found except these, which answer PROXY_NOT_REGISTERED:

SchemeProxy typeValue
PayNow (Singapore)UEN201912345NABC
PayNow (Singapore)MOBILE+6511111111
DuitNow (Malaysia)BUSINESS_REG11111A
DuitNow (Malaysia)MOBILE60121111111

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.

On this page