# Understand the sale lifecycle Building with an AI agent? Start at https://docs.payme.io/agents.md ## Related - [Sale Statuses](/payments/codes-statuses/sale-statuses) - [Sale Types](/payments/codes-statuses/sale-types) - [Callback types reference](/payments/getting-started/callback-types) - [Callbacks](/payments/getting-started/callbacks) - [List sales](/payments/query-apis/post-get-sales) - [List transactions](/payments/query-apis/post-get-transactions) - [Capture an authorized sale](/payments/post-sale-actions/post-capture-sale) - [Refund a sale](/payments/post-sale-actions/post-refund-sale) - [Void an authorization](/payments/post-sale-actions/void-sale) - [Idempotency and Retries](/payments/getting-started/idempotency-and-retries) A sale is PayMe's record of one order. It starts as `initial` when you create it, and its `sale_status` changes as the buyer pays and as you capture, refund or void it. This page shows every transition, what causes it, the callback PayMe sends for it, how long the payment link stays open, and how to read a sale's current state. The status values are listed on [Sale Statuses](/payments/codes-statuses/sale-statuses). The callbacks are described on [Callback types reference](/payments/getting-started/callback-types). ## The states at a glance ```text Charge now (sale_type: sale) initial ──► completed ──► refunded │ ▲ ├───────► partial-refund │ │ └───────► chargeback / partial-chargeback ──► completed (reversed) ▼ │ failed (the buyer can pay again on the same sale) Authorize now, capture later (sale_type: authorize) initial or failed ──► authorized ──► completed (captured) ├────────► failed (capture declined; capture again) ├────────► voided └────────► partial-void ``` ## Transitions | From | To | What causes it | Callback (`notify_type`) | |---|---|---|---| | — | `initial` | You create the sale with `generate-sale` | `sale-create`, only if you sent `sale_send_creation_callback: true` | | `initial`, `failed` | `completed` | The buyer pays | `sale-complete` | | `initial`, `failed` | `authorized` | The buyer pays a sale created with `sale_type: authorize` | `sale-authorized` | | `initial`, `failed` | `failed` | A payment attempt fails: a decline, or a failed 3D Secure check | `sale-failure`, once per failed attempt | | `authorized`, or `failed` after a declined capture | `completed` | [`capture-sale`](/payments/post-sale-actions/post-capture-sale) succeeds. A capture for less than the authorized amount sets the sale price to the captured amount | `sale-complete` | | `authorized` | `failed` | `capture-sale` is declined. You can capture again while the authorization is still valid | `sale-failure` | | `authorized` | `voided` | [`refund-sale`](/payments/post-sale-actions/void-sale) releases the whole hold | `refund` | | `authorized`, `partial-void` | `partial-void` | `refund-sale` releases part of the hold. A `partial-void` sale can't be captured, and further voids keep it `partial-void` | `refund` | | `completed` | `refunded` | [`refund-sale`](/payments/post-sale-actions/post-refund-sale) refunds the full amount at once | `refund` | | `completed`, `partial-refund` | `partial-refund` | `refund-sale` refunds part of the amount. The sale stays `partial-refund` even after the parts add up to the full amount | `refund` | | A paid sale | `chargeback` or `partial-chargeback` | The card issuer charges the payment back, in full or in part | `sale-chargeback` | | `chargeback`, `partial-chargeback` | `completed` | Every chargeback on the sale is reversed in the seller's favor | `sale-chargeback-refund` | | `initial` (template sales only) | `canceled` | [`cancel-template`](/payments/post-sale-actions/post-cancel-template) closes the template's link | None | Some sales are created by PayMe rather than by your `generate-sale` call, and then follow the same statuses: - Each payment on a [template sale](/accepting-payments/checkout-and-in-person/multi-payment-page) (one link that many buyers pay) creates its own sale, `sale_type` `4`. The template itself only moves from `initial` to `canceled`. - Each subscription charge creates a sale, `sale_type` `3`, which sends its own `sale-complete` or `sale-failure`. - An Israeli direct-debit payment sends `sale-paid` when the debit is submitted to the bank, then `sale-complete`, or `sale-failure` if the bank returns it. See [Israeli Direct Debit](/accepting-payments/payment-methods/israeli-direct-debit). Capturing in several parts creates child sales; see [multi-capture](/accepting-payments/capture-and-saved-cards/multi-capture). ## Failures aren't final `failed` means the last attempt failed, not that the sale is closed. The buyer can try again on the same payment page, and you can call [`pay-sale`](/payments/direct-api/post-pay-sale) again on a `failed` sale. Each failed attempt sends another `sale-failure` with its own `payme_transaction_id`. The attempts stop when the sale completes. So: - Don't cancel the order on the first `sale-failure`. Wait for `sale-complete`, or for your own deadline. - If you create a new sale for a retry, the old `sale_url` stays payable too, and the buyer could pay twice. Reuse the same sale, or set `sale_expiry_seconds` on each sale. - Once a sale is `completed`, a late failure can't move it back to `failed`. ## How long the payment link stays open `sale_url` has no fixed expiry. The payment page opens while the sale is `initial` or `failed`; once the sale has any other status, the page no longer takes a payment. To set a deadline, send `sale_expiry_seconds` when you create the sale. The time counts from the sale's creation. After it: - the payment page answers HTTP 403; - `pay-sale` returns error `367` ("the sale has expired"); - `sale_status` doesn't change. An expired sale still reads `initial` or `failed` in `get-sales`, so track the deadline on your side too. `sale_should_be_opened_once: true` works only on a sale with `layout: token-capture`: the page then opens only once. There is no call to cancel an ordinary open sale. To stop a buyer from paying, rely on `sale_expiry_seconds`. `cancel-template` works only on template sales. ## Callbacks at each step The last column of the table above is the callback each transition sends. Three rules matter when you handle them: - `sale-create` is opt-in: PayMe sends it only when you create the sale with `sale_send_creation_callback: true`. - `sale-failure` is sent once per failed attempt, and `refund` once per refund or void. Each carries its own `payme_transaction_id`. - Callbacks can arrive more than once and out of order. Never let a later callback overwrite a final state you already recorded. The payloads, the signature and the delivery rules are on [Callbacks](/payments/getting-started/callbacks). Who receives each type, and its key fields, is on [Callback types reference](/payments/getting-started/callback-types). ## Read the current state Callbacks can be lost after their retries, so confirm a sale with [`get-sales`](/payments/query-apis/post-get-sales) before you fulfil the order, and when a request timed out. `POST https://sandbox.payme.io/api/get-sales` (production: `https://live.payme.io/api/get-sales`) ```json { "seller_payme_id": "MPLDEMO-MPLDEMO-MPLDEMO-1234567", "sale_payme_id": "SALE1655-3843870J-NTPYLJNW-SOWRLK9X", "sale_status": ["initial", "completed", "failed", "authorized", "refunded", "partial-refund", "voided", "partial-void", "chargeback", "partial-chargeback"] } ``` **Send `sale_status`.** Without it, `get-sales` leaves out `initial` sales, so an unpaid sale comes back as an empty `items` list, as if it didn't exist. The response (other fields omitted): ```json { "status_code": 0, "items_count": 1, "items": [ { "seller_payme_id": "MPLDEMO-MPLDEMO-MPLDEMO-1234567", "sale_payme_id": "SALE1655-3843870J-NTPYLJNW-SOWRLK9X", "transaction_id": "order-1002", "sale_type": 1, "sale_status": "completed", "sale_currency": "ILS", "sale_price": 1000, "sale_paid_date": "2026-11-09 12:30:05", "sale_error_code": null, "sale_is_3ds": false } ] } ``` Before you fulfil the order, check that: 1. `sale_status` is `completed` (or `authorized`, if you capture later); 2. `sale_price` and `sale_currency` match your order. `sale_price` is the amount charged, in minor units; 3. `transaction_id` is your own order ID for this order. On a `failed` sale, `sale_error_code` and `sale_error_text` give the reason of the failed payment. `sale_type` tells you where the sale came from, for example `3` for a subscription charge and `4` for a payment on a template sale's link; see [Sale Types](/payments/codes-statuses/sale-types). To see each money movement on its own row (the payment, the capture, every refund and chargeback), use [`get-transactions`](/payments/query-apis/post-get-transactions). There, `transaction_error_code` is `null` on a successful transaction. A sale that is authorized and not yet captured appears only when you send `transaction_type: 40`. If a request timed out and you don't know whether it ran, read the sale before you retry. See [Idempotency and Retries](/payments/getting-started/idempotency-and-retries).