Idempotency
Every payment and session you create carries a merchantInternalTransactionCode — your own unique reference for that operation. AccruPay uses it as the idempotency key: it guarantees that a given code maps to at most one transaction, so a retried or duplicated request cannot create a second charge.
The rule
merchantInternalTransactionCode must be unique per merchant + provider. Before any payment or session is created, AccruPay runs a pre-flight check and rejects the request if that code is already in use — against:
- an existing transaction on the provider,
- a local transaction, or
- a local client transaction session.
If the code is already used, the mutation fails with a uniqueness error (extensions.code is a @…/… AppError key) and nothing is created.
This check runs on every create/start path: merchantApiServerPaymentMethodTransactionCreate, merchantApiServerAchPaymentTransactionCreate, and all client session starts (payment, authorization, add-payment-method).
A code is rejected regardless of the prior transaction's status. A code attached to a FAILED or DECLINED attempt is permanently consumed — it cannot be reused. To retry after a known failure, generate a new merchantInternalTransactionCode.
Choosing a code
- Make it unique and stable for the intent of one payment — e.g.
order-5571-charge,invoice-2026-0042. - Do not reuse a code across logically different operations.
- Generate it on your side before the call so a network retry of the same request is naturally de-duplicated.
Retry semantics
| Situation | What you know | What to do |
|---|---|---|
Mutation returned DECLINED / FAILED | The attempt is final and its code is burned | Retry the payment with a new code (after customer action, if needed). |
| Network timeout / no response | Outcome unknown — the charge may or may not have gone through | Query first by merchantInternalTransactionCode (merchantApiTransaction) to learn the outcome. If a transaction exists, use its status; if none exists, retry with a new code. |
| You resend the exact same request (same code) | — | AccruPay rejects the duplicate rather than charging twice. |
The key safety property: a retry can never silently double-charge, because the second attempt with the same code is rejected, and a deliberate retry uses a fresh code only after you have confirmed the first did not succeed.
Related
- Transactions — query by
merchantInternalTransactionCode - Errors — transaction status vs API errors
- Payment sessions