Docs / Build

Money movement

Loads, QR payment requests, payments, merchant-to-merchant payments, withdrawals, refunds, disputes, statements and reconciliation.

Every movement of money follows the same pattern: your server creates the record, the customer confirms it on the hosted screen with confirmation_session.token, and a webhook reports the final status.

Loads (add funds)#

Shell
curl -X POST https://sandbox.a2ainstapay.com/v1/loads -H "Authorization: Bearer $A2A_ACCESS_TOKEN" -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" -d '{"customer_id":"cus_...","amount":10000}'
StatusMeaning
requires_confirmationWaiting for the customer on the hosted screen
processingThe Request for Payment is at the customer's bank; they approve it in their banking app
settledThe funds are in the Digital Account (load.settled)
failedfailure_code: declined_by_customer, request_expired, rejected_by_bank, confirmation_expired, limit_exceeded or account_restricted

Payment requests (QR codes)#

A merchant shows a QR code; the customer's app scans it and pays it.

TypeUseFields
dynamicOne order, one amountamount, optional order_reference, expires_in (60 seconds to 7 days)
staticA code printed at a counter or till; the customer enters the amountcollection_point.reference and collection_point.name

The response carries qr_payload, signed by A2A InstaPay. Render it as a QR code. A dynamic request becomes paid or expired; a static request stays open.

Payments#

Shell
curl -X POST https://sandbox.a2ainstapay.com/v1/payments -H "Authorization: Bearer $A2A_ACCESS_TOKEN" -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" -d '{"payer_customer_id":"cus_...","source":"balance","qr_payload":"A2AQR1...."}'
KindHowNotes
From balancesource: balanceFinal as soon as the customer confirms (payment.completed)
Pay by banksource: bank_accountpayment.processing, then payment.completed when the payer's bank pays the Request for Payment
To a merchant without a QR codepayee_customer_id and amountFor example an online checkout
Merchant to merchantA merchant pays another merchantFrom balance only, with invoice_reference

A payment can be canceled with POST /v1/payments/{id}/cancel only while it waits for confirmation. Completed payments are final; they can be returned only by a merchant refund.

Withdrawals#

POST /v1/withdrawals with customer_id and amount sends an RTP credit transfer to the verified linked account. The amount is reserved when the customer confirms. withdrawal.settled or withdrawal.failed follows.

Refunds#

Shell
curl -X POST https://sandbox.a2ainstapay.com/v1/refund-requests -H "Authorization: Bearer $A2A_ACCESS_TOKEN" -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" -d '{"payment_id":"pay_...","amount":1000,"reason":"requested_by_customer"}'

The merchant's authorized user confirms the refund on the hosted screen. If the merchant's balance is short, the refund waits as pending_funds and continues when funds arrive. A refund goes back the way the payment came: to the payer's balance, or by RTP to the payer's bank. refund.updated reports each step, and payment.partially_refunded or payment.refunded follows. Refunds are possible within your program's refund window (30 days in the sandbox), and never for more than the original amount less earlier refunds.

Disputes#

Record a customer's notice with POST /v1/disputes: type is error, unauthorized_transfer or purchase_dispute, with notice_received_at. Consumer disputes about errors and unauthorized transfers are handled under Regulation E, with provisional credit while the investigation runs. dispute.updated reports each step: received, investigating, provisional_credit, resolved, closed.

Limits and fees#

Limits apply per transaction and per day and month, by amount and by count. An amount over a limit returns limit_exceeded with details.limit. Fees appear in fees on each payment, with net_amount for the merchant. Your program's limits and fees are agreed with FINAP USA LLC; in the sandbox you can change them in the portal settings to test.

Statements and reconciliation#

  • GET /v1/accounts/{id}/statements lists monthly statements; download_url is valid for 15 minutes. statement.available announces each one.
  • GET /v1/reports/reconciliation?date=YYYY-MM-DD gives the totals of a business date (US Eastern Time) and a CSV with every posting, to reconcile your records with A2A InstaPay's ledger.

Questions about this page? Contact developer support.