Quick Start
This guide takes you from zero to your first payment in the sandbox. You will authenticate, fund an account, verify a beneficiary, and pay them. The flow is the same one you will run in production.
Before you startYou need a sandbox account and your public keys registered with IBANQ. If you haven't done that yet, follow the Authentication & Request Signing Guide first. It walks through generating your three key pairs (authentication, DPoP, signing) and emailing the two public keys that need registering to your account manager. Come back here with your
applicationId, your clientId and signingkeyid.
Every sandbox API call goes to https://api.sandbox.ibanq.com and every path is prefixed with /v1. Access tokens come from a different hostname, https://auth.sandbox.ibanq.com.
1. Get an access token
Request a token with a private_key_jwt client assertion (signed with your authentication key, PS256) and a DPoP proof (signed with your DPoP key). The assertion identifies you by your application ID, not your client ID: put the application ID in its iss and sub claims. The audience field is required, and is matched literally against the registered API identifier, so copy it exactly with no trailing slash:
POST /oauth/token HTTP/1.1
Host: auth.sandbox.ibanq.com
DPoP: <dpop_proof_jwt>
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&audience=https://api.sandbox.ibanq.com
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion=<private_key_jwt>
&scope=The response is a DPoP-bound token (token_type: DPoP). Tokens are short-lived: read expires_in and request a new token shortly before it expires rather than caching one long-term. Auth0 returns the full set of scopes delegated to your application, so you cannot narrow a token down by asking for less. The scope field is not usable here: populating it will not change the scopes you receive back, because Auth0 only applies it to other connection types, so we recommend leaving it blank. If you need your delegated scopes changed, reach out to your account manager.
2. Make your first call
Every request carries the token in the DPoP authorization scheme plus a fresh DPoP proof whose htm and htu match the request. htu is scheme, host and path only, with no query string:
GET /v1/reference/currencies HTTP/1.1
Host: api.sandbox.ibanq.com
Authorization: DPoP <access_token>
DPoP: <fresh_dpop_proof>The response lists the supported currencies with their minor-unit precision. You will need this for amounts, which are integers in minor units (pence, cents) on every endpoint, including FX quotes and trades.
3. Find your account
GET /v1/accounts HTTP/1.1
Host: api.sandbox.ibanq.com
Authorization: DPoP <access_token>
DPoP: <fresh_dpop_proof>Note the account's id and its account identifier. You will fund it next and pay out of it in step 6. Add ?includeBalances=true if you want the per-currency balances in the same call.
4. Fund the account (sandbox only)
The sandbox lets you simulate an inbound payment so you have a balance to pay out of. Simulation endpoints are the one place where request signing is not required:
POST /v1/simulations/inbound-payments HTTP/1.1
Host: api.sandbox.ibanq.com
Authorization: DPoP <access_token>
DPoP: <fresh_dpop_proof>
Content-Type: application/json
{
"clientId": "<your client id or sub account client id>",
"accountId": "<your account id>",
"amount": 100000,
"currency": "GBP",
"paymentType": "Fps",
"reference": "QUICKSTART FUNDING"
}
Sub account fundingSub accounts have their own clientId values. To fund a sub account, you must provide the sub account's own clientId and an accompanying accountId that exists under the client. You can verify these details with the accounts querying step above.
paymentType accepts Fps, Chaps, Swift or Sepa.
This returns 202 with the created inbound payment's id and credits 1,000.00 GBP to your account (amounts are in minor units), the same way a real inbound Faster Payment would.
The credit is processed asynchronously. The inbound payment is readable at once with status Processing; it moves to Received and the balance appears in GET /v1/accounts?includeBalances=true shortly after, which can take up to a minute in the sandbox. An account with no ledger activity yet returns an empty balances array, not a zero balance.
5. Verify the beneficiary and create a payee
GB sort-code payees need a Confirmation of Payee check first. Verify the name:
POST /v1/account-name-verifications HTTP/1.1
Host: api.sandbox.ibanq.com
Authorization: DPoP <access_token>
DPoP: <fresh_dpop_proof>
Content-Type: application/json
{
"clientId": "<your client id>",
"accountHolderName": "Jane Smith",
"accountType": "Personal",
"sortCode": "040004",
"accountNumber": "12345678"
}The response contains the verification outcome and an id. Pass it when creating the payee. A verification rejected with reason AC01 cannot be used:
POST /v1/payees HTTP/1.1
Host: api.sandbox.ibanq.com
Authorization: DPoP <access_token>
DPoP: <fresh_dpop_proof>
Content-Type: application/json
{
"clientId": "<your client id>",
"nameOnAccount": "Jane Smith",
"accountNumber": "12345678",
"domesticBankCode": "040004",
"bankCountry": "GB",
"country": "GB",
"type": "Individual",
"accountNameVerificationId": "<verification id>"
}Bank details are validated against the bank country's rules and the bank name is resolved automatically.
6. Send the payment
Creating a payment moves money, so this request must also be signed with your signing key (see request signing). That means three extra headers on top of the usual two:
POST /v1/outbound-payments HTTP/1.1
Host: api.sandbox.ibanq.com
Authorization: DPoP <access_token>
DPoP: <fresh_dpop_proof>
Content-Digest: sha-256=:<standard-base64 SHA-256 of the exact body bytes>:
Signature-Input: sig1=("@method" "@target-uri" "content-digest" "content-type");created=<unix_seconds>;keyid="<your_keyid>";alg="rsa-pss-sha256"
Signature: sig1=:<standard-base64 signature>:
Content-Type: application/json
{
"clientId": "<your client id>",
"payeeId": "<payee id from step 5>",
"accountId": "<account id from step 3>",
"amount": 25000,
"currency": "GBP",
"reference": "QUICKSTART PAYMENT",
"idempotencyKey": "quickstart-payment-001"
}This sends 250.00 GBP to Jane. If you leave paymentMethod blank, the rail is resolved from the payee and account capabilities.
Four things that break signaturesThe four covered components must appear in exactly the order shown,
algmust bersa-pss-sha256,createdmust be within 60 seconds of server time, andContent-Typemust be exactlyapplication/jsonwith nocharsetsuffix. Serialise the body once and compute both the digest and the signature over those exact bytes. Note that the signed@target-uriincludes any query string, while the DPoPhtudoes not.
You choose the idempotencyKey (up to 100 characters). Retrying the identical request with the same key returns 200 with the original payment's id instead of creating a duplicate, so if you ever lose a response you can recover the payment by retrying. Reusing a key with different details is rejected with 409, whose body carries existingPaymentId when a payment already exists under that key. See Idempotency for the full rules, including the copyNumber field you need when you genuinely want to send the same payment twice.
7. See the result
Status transitions are asynchronous, so poll the payment until it reaches a terminal status. The response also carries an events array listing every event raised for the payment so far, so you can see how it got to its current status without a second call:
GET /v1/outbound-payments/{id} HTTP/1.1
Host: api.sandbox.ibanq.com
Authorization: DPoP <access_token>
DPoP: <fresh_dpop_proof>A plain reference takes the happy path and ends at Sent, at which point the account is genuinely debited. Then look at the ledger:
GET /v1/transactions HTTP/1.1
Host: api.sandbox.ibanq.com
Authorization: DPoP <access_token>
DPoP: <fresh_dpop_proof>You will see the simulated credit and the debit from your outbound payment, with direction, value date (UK business date) and amounts in minor units.
Where next
- Authentication & Request Signing: the full key, token, DPoP and RFC 9421 signing reference.
- Idempotency: retry semantics, key rules and the
copyNumberescape hatch. - Status codes: every status code, the problem-details error format and what is safe to retry.
- Sandbox Outcome Triggers: drive payments, FX trades and name checks to any outcome, including failures.
- Creating payees: required fields per destination,
bankCountryversuscountry, and Confirmation of Payee. - Creating a payment: every field on an outbound payment, purpose codes, ultimate debtor and cancellation.
- Buying and selling currency: the quote-then-trade flow,
fixedSide, and how FX amounts use minor units and the Amount object. - Payment lifecycle and statuses: what happens after a payment is created, and what each status means.
- Enums and allowed values: the fixed value sets the generated reference types as plain strings.
- Pagination and filtering: the list envelope, paging defaults and filter conventions.
- Amounts, currencies and dates: minor units, the
Amountobject and UK business dates. - Going from sandbox to production: what changes at go-live, and a checklist for getting there safely.
- API Reference: every endpoint, request and response, generated from our OpenAPI spec.
Updated 10 days ago