Skip to main content
The sandbox is a separate deployment of the Infinity API that runs the same code as live, connected to a simulated payout network instead of real banks. Requests, responses, validation, idempotency, statuses and webhooks behave as they do in production; only the movement of funds is simulated. Use it to build your integration and to test the outcomes that are rare in production, such as failures and bank returns. Sandbox keys are issued by our team. Contact us with your company name and we’ll set up your sandbox account and send you an sk_test_ key.

How the sandbox differs from live

Test helpers

Test helpers are endpoints under /test that stand in for things a real bank, payee or scheduler would do. They exist only in the sandbox; on the live host they return 404 path_not_found. Each helper runs the same internal path the real event would, so it fires the same webhooks.

Fund a wallet

The Idempotency-Key header is required, as on every request that moves money. The response is a deposit with rail: null, which marks a manual credit, and Infinity emits deposit.created. A deposit doesn’t release payouts that are waiting for funds, in the sandbox or in live. They’re released by the daily release, which you trigger here with release payouts on hold.

Activate a payee

Skips hosted onboarding: Infinity adds a test bank account to the payee through the normal address path, and the payee becomes active.
The test account uses the payee’s name as the account holder and Sandbox Bank as the bank. Only payees in invited or details_pending can be activated; an active payee returns 409 payee_already_active, and a verifying or inactive payee returns 409 test_transition_not_allowed. The response is the payee with status: active, and Infinity emits payee.active.

Force a payout outcome

  • failure_code is accepted only with to: failed. Allowed values are undeliverable (the default), refunded, refund_failed, canceled and processing_error.
  • A 202 response returns the payout as it is at that moment. The new status lands asynchronously, usually within 2 seconds, through the same webhook path a real network status takes. Read it from the event or from GET /payouts/{id}, exactly as you would in production.
  • Any other transition returns 409 test_transition_not_allowed. To cancel, use the regular cancel endpoint.

Release payouts on hold

In live, payouts on hold are released once a day at 09:00 IST. This helper runs that release immediately, for your account only:
Response
Each payout that changes status emits its own events, as the daily release does.

Simulating a rejected bank account

Any account number ending in 0000 passes format validation and is then rejected by the simulated network with 400 bank_details_invalid and param: null, which is how a real bank-side rejection appears.

Common test scenarios

  1. Create a payee without a bank account.
  2. Create a payout to them. It’s created as awaiting_payee and the amount is reserved in the wallet.
  3. Activate the payee with the helper.
  4. Release payouts on hold. The payout moves to pending, then to paid.
  1. Create a payout and wait for payout.paid.
  2. Advance it with { "to": "returned" }.
  3. Handle payout.returned, and the batch event that follows when the batch’s status changes.
  1. Create a payee.
  2. Add an address with an account number ending in 0000.
  3. Handle 400 bank_details_invalid with param: null; the payee’s status doesn’t change.

Limitations

The helpers cover outcomes that occur after a payout is sent. Failures that occur while sending (below_minimum, bank_details_invalid, rate_changed, bank_account_missing) can’t be simulated yet. insufficient_funds occurs naturally when a wallet’s available balance is too low.