A checkout has one or more charges — one per payment attempt. A checkout has at most one review.
Charge Status Lifecycle
A charge starts atcreated and moves through the transitions below. failed, returned, cancelled and refunded are terminal — no further transition is possible.
Note that
succeeded is not terminal. A settled charge can later be reversed by the processor, which is why you can receive checkout.failed with from_status: "succeeded" for a payment you already credited.
Which transition emits which webhook
Not every status has a corresponding event. Three have none at all.cancelled and refunded are not notified. cancelled applies to bank-transfer payments cancelled while still pending. refunded is set when Soap refunds a settled charge out-of-band — through a payment partner rather than through the API — and reconciles it afterwards; nothing produces it automatically, so it does not follow from anything you do through the API.Soap sends no event for either. If you need to observe them, read the charge with GET /api/v1/charges/{id}.failed that matter when reconciling withdrawals:
- The same status produces two different events depending on where the charge came from. A withdrawal that fails after a hold was placed emits
checkout.release_hold; a withdrawal that fails before reachingheldemitscheckout.failed, which is off by default. Both mean you should release the hold. checkout.holdis delivered before the charge moves toheld. If your endpoint does not return success, Soap fails the charge while it is stillcreated— so you receivecheckout.failed, notcheckout.release_hold. Seecheckout.hold.
One Checkout, Several Charges
Each payment attempt creates a new charge with a newch_ id. When an attempt fails, the customer returns to the payment form; their next submission is a new attempt against the same checkout. A customer whose card is declined and who then pays with a different method leaves behind two charges: one failed, one succeeded.
Soap enforces at most one charge per attempt. It does not limit how many attempts a checkout can accumulate, so do not assume a fixed number of charges per checkout.
Two consequences worth designing around:
- The charge returned when you read a checkout is the latest attempt’s charge. Earlier attempts are not listed on it.
- Because
checkout.failedis off by default, a merchant who has not enabled it receives no notification of the earlier failed attempts and has no charge id for them. If you need attempt-level history, enablecheckout.failedin Dashboard → Developers.
Checkout Outcomes
A checkout is in progress from creation until the customer finishes it or it expires, which is 30 minutes after creation by default. There is no checkout status field, and no endpoint to poll a checkout’s state after you create it — you observe outcomes through webhooks.There is no terminal-success event for the checkout itself. Success is signalled by the charge events, which is why the list above mixes charge-level and checkout-level events.Both
checkout.expired and checkout.terminally_failed are off by default, so a merchant who has enabled nothing extra receives no webhook at all for an abandoned or blocked checkout.Reviews
Some withdrawals are routed to manual review before any payment is attempted. Review is disabled by default and enabled per account, and the criteria that select a withdrawal for review are configured per account — so some withdrawals enter review and others do not. Today everycheckout.review.* event you receive will carry "type": "withdrawal".
A review is created before the charge exists. Soap creates the review and pauses the checkout instead of submitting the payment, which means:
- There is no charge during the review window, so no charge status can change and you will receive no charge-based webhook for that checkout while the review is open.
- On approval, Soap creates the charge and places the hold at that point —
checkout.holdarrives then, followed by the normal withdrawal events. - On decline, no charge is ever created. Neither
checkout.failednorcheckout.release_holdcan fire, because there was never a charge to fail.

