Testing in Sandbox

How to run a flow end to end in the test environment.

https://api.sandbox.alfredpay.io

Sandbox is contract-identical to production. The requests, the responses, the event payloads and the errors are all the same. The only difference is that two simulator endpoints exist here. On production they return 404 not_found.

Those two endpoints remove the two waits you cannot otherwise control.

Adding money to a sandbox account

You cannot transfer funds into a sandbox account, and no starting balance is provisioned for you. You simulate a deposit.

POST /v1/test/customers/{customerId}/deposits/simulate

In production a deposit arrives because a payer sent money, so there is nothing for you to call. In sandbox this stands in for the payer.

The simulator runs the real pipeline. Detection, attribution and events all run. Screening, conversion and crediting run as well. What you get back is a deposit that went through the same code as a real one, which is what makes it worth testing against.

Idempotency-Key is required here, the same as on any other POST.

Wait for deposit.credited before you treat the funds as spendable, the same as you would in production.

Skipping the destination review queue

POST /v1/test/linked_accounts/{linkedAccountId}/simulate_activation

This moves a relationship straight to VERIFIED.

Registering a payout destination normally goes through a review, and you do not control how long that review takes. Without the simulator, testing a payout flow means registering a destination and then waiting on someone else's process. With it, the whole flow runs in a minute.

Calling it again returns the same already-verified account.

A full pass

Here is what a complete run looks like and what to check at each point.

  1. Create a customer with POST /v1/customers and then PUT the profile. Check that it reads NOT_STARTED.
  2. Onboard the customer by submitting the information and uploading the documents. Run preflight until it comes back clean, then submit the verification and check that you reach ACTIVE.
  3. Request an endorsement, using fiat_collection for collections. Wait for APPROVED and check provider_endorsements[] as well.
  4. Create a virtual account. Check that virtual_account.activated fires and that the deposit instructions come back.
  5. Simulate a deposit and watch the four statuses move. Check that deposit.credited arrives.
  6. Read the balance and check that the amount landed in available and not only in total.
  7. Register a destination and then activate it with the simulator. Check that supportedRails[] is what you expected.
  8. Request a quote and pay out. Check that the rail on the quote matches the destination and that the payout reaches COMPLETE with SETTLED.

If any step depends on a status you have not seen before, read all four statuses instead of only the one you were watching.

Cases beyond the successful path

These cases are worth testing explicitly, because they are the ones that tend to cause problems in production.

  • Send the same event twice and confirm your handler is idempotent.
  • Send an event you do not handle and confirm you return a 2xx instead of failing. See Webhooks and events.
  • Let a quote pass expiresAt and confirm you re-quote instead of retrying.
  • Revoke an endorsement and confirm your integration notices instead of failing silently later.
  • Ask for a route that is not LIVE and confirm you handle route_unsupported before anything is locked.
  • Try to pay out with insufficient balance and confirm you read the balance instead of retrying into the same 422.

You can reach most of these by hand. An expired quote only needs you to wait, and an unsupported route is any combination the registry does not list as LIVE. To produce a rejection or an RFI on a customer, ask your Alfred contact which test values to use.

What sandbox will not tell you

Timing

Sandbox decisions come back in seconds. Real KYB, real settlement and real rail behavior take much longer. Do not build a timeout from what you see here.

Coverage

A route can read SANDBOX in the registry. That means it is available and tested here but not enabled in production. Check the status on each route instead of assuming that something working here also works there.


Did this page help you?