Payments
The payment state machine — every status, every legal transition, and what triggers each one.
A Payment is the record of one charge attempt against a customer. It's created when you call POST /payments, and it moves through a state machine until it reaches a terminal state (failed, refunded, or voided).
The state machine
Terminal states: failed, refunded, voided. Once a payment reaches one, no more transitions happen.
succeeded is "soft terminal" — most payments stop there, but a refund or void can still move them onward.
Allowed transitions
| From | Allowed to |
|---|---|
created | pending, authorized, succeeded, failed |
pending | authorized, succeeded, failed |
authorized | succeeded, failed, voided |
succeeded | refunded, partially_refunded, voided |
partially_refunded | refunded, partially_refunded, voided |
failed | (terminal) |
refunded | (terminal) |
voided | (terminal) |
Same-status transitions are treated as idempotent — webhooks that arrive twice for the same state change don't break anything.
Out-of-order transitions should be rejected. If a payment is already succeeded and a stale pending webhook arrives, you should refuse the transition and the payment stays succeeded.
Two ways a payment starts
Hosted payment page (HPP)
We give you a redirectUrl; the customer fills the form on the provider's hosted page.
Token charge (saved card)
You have a cardToken from a previous successful charge. The customer doesn't see a payment page — the charge happens server-to-server.
What you receive on each state
Every state transition fires a webhook. The full table is in Webhooks → Event types, but in short:
| State | Webhook event | Should you fulfil? |
|---|---|---|
pending | payment.pending | No — wait for succeeded |
authorized | payment.authorized | Reserve inventory, but don't ship yet |
succeeded | payment.succeeded | Yes — fulfil the order |
failed | payment.failed | Release inventory; inform the user |
partially_refunded | payment.partially_refunded | Update internal balance; partial refund flow may continue |
refunded | payment.refunded | Mark order refunded |
voided | payment.voided | Treat as failed for accounting; release inventory |
Always fulfil on the webhook
The synchronous response from POST /payments tells you the request was
accepted, not that the customer was charged. Wait for payment.succeeded
before granting credit, releasing inventory, or sending a "thanks for your
purchase" email.
Idempotency
Every POST /payments accepts an externalId — your unique identifier for that order. If the same externalId arrives twice, MintCash returns the original payment record and never calls the provider again. Use this to make retries safe.