APG PayAPG Paydocs

Going live

Testing

Make things happen in sandbox that you cannot wait for in real life.

Sandbox is a separate world with separate credentials and separate data. Nothing you do there touches real money, and nothing you do in production can be undone by pretending it was a test.

Some outcomes take days in reality, a dispute being raised, an authorisation clearing. A simulation makes one happen now so you can build against it.

Request
curl -X POST "https://api.tst.au.apgpay.dev/bezel/simulations" \
  -H "Authorization: Bearer $API_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "transactionId": "<useTransactionIdFromSeed>",
  "disputeAmount": null,
  "type": "SimCmdDispute"
}'
Test the failures, not just the happy path. A declined card, an expired authorisation, a blocked bank account and a permanently failed payout are all states your integration will meet, and the first three are easier to trigger deliberately in sandbox than to handle for the first time in production.

Test cards

These work in sandbox and nowhere else. Any future expiry, any CVC.

4242 4242 4242 4242   Visa credit
4000 0566 5566 5556   Visa debit
5555 5555 5555 4444   Mastercard credit
5200 8282 8282 8210   Mastercard debit
5105 1051 0510 5100   Mastercard prepaid
3782 822463 10005     American Express

Each of these is refused with a 400 and the errorCode named beside it, which is what you branch on:

4000 0000 0000 9995   insufficient_funds
4000 0000 0000 9987   lost_card
4000 0000 0000 9979   stolen_card
4000 0000 0000 0069   expired_card
4000 0000 0000 0127   invalid_cvc
4100 0000 0000 0019   fraudulent

4000 0025 0000 3155 authorises but demands a 3-D Secure challenge first, which is the one to use when you are building the challenge handling rather than avoiding it.

On a Fiserv-acquired merchant the decline comes from the amount, not the card. That sandbox reads the last three digits of the minor-unit amount: 770 is insufficient funds, 775 a lost card, 776 an invalid CVC. The card number only decides which decline the receipt names, so both halves have to agree, and a decline card charged a round amount simply succeeds. If you are testing refusals and getting approvals, this is why.

Testing 3-D Secure

On a merchant acquired by the sandbox mock acquirer the last three digits of the minor-unit amount select the authentication outcome, the same way the amount selects a decline.

301         challenge, passes when it is completed
302         challenge, refused when it is completed
303         authentication unavailable, the payment proceeds without a liability shift
304         not supported, the payment proceeds without a liability shift
305         refused before any challenge
306         challenge, and the payer chooses the outcome on the page
307         challenge whose URL leads nowhere, for testing a provider that misbehaves
any other   frictionless pass

An amount of 10301 is challenged and passes, and 10302 is challenged and refused.

306 is the one to use by hand. The others settle the moment the challenge URL is opened, with nothing rendered, which suits a script and shows a person nothing. 306 serves a page with an approve and a decline button, and the button pressed is the outcome, so both paths are reachable from the one amount.

307 hands back a challenge URL that returns a 404. The payment stays waiting on a challenge that can never be completed, which is what a provider having a bad day looks like to you.

The "authentication required" response carries the challenge URL. In sandbox, open it directly: it completes the challenge and redirects to the returnUrl, and the payment is then finished with the continuation exactly as the 3-D Secure guide shows.

4000 0025 0000 3155 applies to Stripe-acquired merchants only.

Before you go live, check three things that are easy to miss: that you branch on errorCode rather than message text, that you verify webhook signatures, and that you read the resource's own status rather than inferring success from an HTTP 200.