# Pay a sale Building with an AI agent? Start at https://docs.payme.io/agents.md - Sandbox: `POST https://sandbox.payme.io/api/pay-sale` - Production: `POST https://live.payme.io/api/pay-sale` ## Credentials - Request body field `token` (optional): A partner-level token to pay with instead of the card fields: the `uuid` from [Create a partner-level token](/payments/tokenization/post-sellers-mpl-tokens). ## Overview Charges a card, or a saved card, on a sale you created with [`generate-sale`](/payments/hosted-payment-page/post-generate-sale). Use it in the [Direct API](/payments/direct-api) (PCI DSS Level 1 partners only) and to finish a [Hosted Fields](/payments/hosted-fields-jsapi) payment. This call takes no credentials: PayMe finds the sale by `payme_sale_id`, and the price, currency and callback URLs come from the sale. Treat `payme_sale_id` like the payment link: share it only with the buyer who pays it. Send either the card fields (`credit_card_number`, `credit_card_exp`, `credit_card_cvv`) with `buyer_name` and `buyer_email`, or a saved card in `buyer_key` (or a partner-level `token`). With `buyer_key` or `token`, PayMe uses the saved card's details and needs no CVV. ### Reading the result The response is synchronous. PayMe also sends the sale [callbacks](/payments/getting-started/callbacks). Read `status_code`: | `status_code` | Meaning | What to do | |---|---|---| | `0` | Paid. On a sale created with `sale_type: "authorize"`, authorized: charge it later with [`capture-sale`](/payments/post-sale-actions/post-capture-sale). On a `token` sale, the card is saved and not charged. | Read `sale_status`. | | `1` | Declined, with HTTP 200. `status_error_code` and `status_error_details` give the reason. The sale becomes `failed` and can be paid again. | Ask the buyer for another card. | | `5` | The card issuer asks for a 3D Secure challenge. | Send the buyer's browser to `redirect_url`. The result arrives in the sale callback. | ### Before you call - The sale must be `initial` or `failed`; otherwise the call returns error `305` with the sale's status in `status_additional_info`. An expired sale returns `367`. - Only card sales can be paid here: a sale created for another payment method returns error `2`. - A value that looks like a card number in any field other than `credit_card_number` is rejected with HTTP 400, error `20`. - Send one call per sale at a time. A second call while the first is still running returns HTTP 429, error `998`. ## Parameters This endpoint takes no path, query or header parameters. ## Request body Content type: `application/json` | Field | Type | Required | Description | | --- | --- | --- | --- | | `payme_sale_id` | string | yes | The sale to pay: the `payme_sale_id` that `generate-sale` returned. | | `credit_card_number` | string | no | Card number, digits only. Required unless you send `buyer_key` or `token`. | | `credit_card_exp` | string | no | Card expiry as `MMYY` (`MM/YY` and `MMYYYY` are also accepted). Required unless you send `buyer_key` or `token`. | | `credit_card_cvv` | string | no | CVV, 3 or 4 digits. Required with the card fields unless `token_terminal` is `true`. On a sale whose `layout` is `token-capture` or `dynamic-loose`, leaving it out sends the payment to a token terminal. | | `token_terminal` | boolean | no | `true` to charge the card fields without a CVV, on a token terminal. Default `false`. | | `buyer_key` | string | no | A saved card to pay with instead of the card fields. See [Save a card as a token](/payments/tokenization/post-capture-buyer-token). | | `token` | string | no | A partner-level token to pay with instead of the card fields: the `uuid` from [Create a partner-level token](/payments/tokenization/post-sellers-mpl-tokens). | | `buyer_name` | string | no | Buyer's full name. Required, with `buyer_email`, when you pay with the card fields, unless the sale's `layout` is `token-capture` or `dynamic-loose`. | | `buyer_email` | string | no | Buyer's email address. Same rule as `buyer_name`. | | `buyer_phone` | string | no | Buyer's phone number. | | `buyer_social_id` | string | no | Buyer's national ID number, digits only. Ignored when you pay with `buyer_key` or `token`. | | `buyer_zip_code` | string | no | Buyer's zip code, letters and digits only; anything else returns error `37`. | | `buyer_business_code` | string | no | For a business buyer: its registration number. Send it with `buyer_business_name`, or neither. | | `buyer_business_name` | string | no | For a business buyer: its name. Send it with `buyer_business_code`, or neither. | | `installments` | integer | no | Number of installments the buyer chose. Required only when the sale lets the buyer choose (a sale created with `installments` above `100`, such as `106`); otherwise the sale's own value is used. | | `payment_method` | string | no | On a sale that offers several payment methods: the method being paid. Default `credit-card`. | | `manual_auth_number` | string | no | An authorization code from the card issuer (voice authorization), to re-run a `failed` sale. Send it with `buyer_key` or `token`. | | `xid` | string | no | If you ran 3D Secure yourself: its transaction ID. With `xid`, PayMe doesn't run its own 3D Secure. | | `eci` | string | no | If you ran 3D Secure yourself: the ECI value. Send it with `xid`. | | `cavv` | string | no | If you ran 3D Secure yourself: the CAVV value. Send it with `xid`. | | `3ds_version` | string | no | If you ran 3D Secure yourself: the protocol version. Send it with `xid`. | | `meta_data` | object | no | Browser data for 3D Secure, as an object. Send this or `meta_data_jwt`. See [3DS with Hosted Fields](/accepting-payments/3d-secure/3ds-with-hosted-fields). | | `meta_data_jwt` | string | no | Browser data for 3D Secure, as the JWT Hosted Fields gives you. Send this or `meta_data`. See [3DS with Hosted Fields](/accepting-payments/3d-secure/3ds-with-hosted-fields). | | `sale_additional_data` | object | no | Extra data to store on the sale. | | `language` | string | no | Language of error messages: `en`, or `he` (the default). `es`, `ru` and `ar` are accepted, but messages then come back mostly in English. Any other value returns error `51`. | ### Request example ```json { "payme_sale_id": "SALEDEMO-XXXXXXXX-XXXXXXXX-XXXXXXXX", "credit_card_number": "5326105300985846", "credit_card_exp": "1230", "credit_card_cvv": "658", "buyer_name": "Israel Israeli", "buyer_email": "buyer@example.com", "buyer_social_id": "008336174", "language": "en" } ``` ## Code samples ### curl ```bash curl -X POST 'https://sandbox.payme.io/api/pay-sale' \ -H 'Content-Type: application/json' \ --data-raw '{ "payme_sale_id": "SALEDEMO-XXXXXXXX-XXXXXXXX-XXXXXXXX", "credit_card_number": "5326105300985846", "credit_card_exp": "1230", "credit_card_cvv": "658", "buyer_name": "Israel Israeli", "buyer_email": "buyer@example.com", "buyer_social_id": "008336174", "language": "en" }' ``` ### Node.js ```javascript const response = await fetch("https://sandbox.payme.io/api/pay-sale", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ "payme_sale_id": "SALEDEMO-XXXXXXXX-XXXXXXXX-XXXXXXXX", "credit_card_number": "5326105300985846", "credit_card_exp": "1230", "credit_card_cvv": "658", "buyer_name": "Israel Israeli", "buyer_email": "buyer@example.com", "buyer_social_id": "008336174", "language": "en" }), }); console.log(await response.text()); ``` ### Python ```python import requests response = requests.post( "https://sandbox.payme.io/api/pay-sale", json={ "payme_sale_id": "SALEDEMO-XXXXXXXX-XXXXXXXX-XXXXXXXX", "credit_card_number": "5326105300985846", "credit_card_exp": "1230", "credit_card_cvv": "658", "buyer_name": "Israel Israeli", "buyer_email": "buyer@example.com", "buyer_social_id": "008336174", "language": "en", }, ) print(response.text) ``` ### PHP ```php 'POST', CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', ], CURLOPT_POSTFIELDS => $body, ]); $response = curl_exec($ch); curl_close($ch); echo $response; ``` ## Responses ### 200 — The payment result: paid (`status_code` `0`), declined (`1`) or a 3D Secure challenge (`5`). A decline also returns HTTP 200. (success) | Field | Type | Description | | --- | --- | --- | | `status_code` | integer | `0`: paid (or authorized, or the card saved on a `token` sale). `1`: declined. `5`: 3D Secure challenge; send the buyer to `redirect_url`. | | `status_error_code` | integer | `0` on success; the decline code when `status_code` is `1`. | | `status_error_details` | string | The decline reason, when `status_code` is `1`. | | `redirect_url` | string | With `status_code` `5`: the 3D Secure page to send the buyer to. On a paid sale: the sale's return URL, or `null`. | | `status_message` | string | With `status_code` `5`: a message you can show the buyer. | | `cancel_url` | string | The sale's cancel URL, or `null`. | | `payme_status` | string | Legacy field. Read `status_code` instead. | | `payme_sale_id` | string | The sale's ID. | | `payme_sale_code` | integer | The sale's numeric code. | | `sale_created` | string | When the sale was created, `YYYY-MM-DD HH:MM:SS` (Israel time). | | `sale_status` | string | The sale's status, for example `completed`, `authorized` or `failed`. See [Sale Statuses](/payments/codes-statuses/sale-statuses). | | `payme_sale_status` | string | Same as `sale_status`. | | `sale_type` | string | The sale type as responses name it, for example `Sale` (also for an authorization) or `Token`. | | `sale_payment_method` | string | Payment method, for example `credit-card`. | | `currency` | string | Sale currency, an ISO 4217 code such as `ILS`. | | `price` | integer | Sale price in minor units (`10000` = 100.00). | | `transaction_id` | string | Your own reference for the sale. | | `sale_description` | string | The sale's description. | | `sale_deferred_months` | integer | Deferred months on the sale, or `null`. | | `is_token_sale` | boolean | `true` for a `token` sale, which saves the card without charging it. | | `payme_signature` | string | PayMe's signature for this payment. | | `payme_transaction_id` | string | PayMe's ID of the payment transaction. | | `payme_transaction_total` | string | Amount of the transaction, in minor units. | | `payme_transaction_card_brand` | string | Card brand, for example `Mastercard`. | | `payme_transaction_auth_number` | string | Authorization number from the card issuer. | | `payme_transaction_voucher` | string | Voucher number of the transaction. | | `payme_transaction_emv_uid` | string | EMV UID of the transaction, when the acquirer returns one; usually `null`. | | `payme_transaction_acquirer` | string | The acquirer, for example `PayMe`. | | `payme_transaction_auth_source` | string | Authorization source reported for the transaction. | | `payme_transaction_card_issuer` | string | Card issuer, for example `Isracard`. | | `payme_transaction_credit_type` | string | Credit type, for example `RegularCredit`. | | `buyer_name` | string | Buyer's full name. | | `buyer_email` | string | Buyer's email address. | | `buyer_phone` | string | Buyer's phone number, or `null`. | | `buyer_card_mask` | string | Masked card number, for example `532610******5846`. | | `buyer_card_exp` | string | Card expiry, `MMYY`. | | `buyer_card_is_foreign` | boolean | `true` for a card issued outside Israel. | | `buyer_social_id` | string | Buyer's national ID number, or `null`. | | `installments` | integer | Number of installments. | | `transaction_first_payment` | integer | First installment, in minor units. | | `transaction_periodical_payment` | integer | Each later installment, in minor units; `0` for a single payment. | | `transaction_arn` | string | Acquirer reference (EMV UID) when the acquirer returns one; usually `null`. | | `sale_paid_date` | string | When the payment was made, `YYYY-MM-DD HH:MM:SS` (Israel time). | | `sale_release_date` | string | Date the funds are released to the seller, `YYYY-MM-DD`, or `null`. | | `sale_3ds` | boolean | `true` when the payment passed 3D Secure. | | `session` | string | PayMe's ID for this request. Quote it when you contact PayMe. | ```json { "status_code": 0, "status_error_code": 0, "payme_status": "success", "payme_sale_id": "SALEDEMO-XXXXXXXX-XXXXXXXX-XXXXXXXX", "payme_sale_code": 1111111, "sale_created": "2026-11-09 10:15:02", "sale_status": "completed", "payme_sale_status": "completed", "sale_type": "Sale", "sale_payment_method": "credit-card", "currency": "ILS", "price": 10000, "transaction_id": "order-1234", "sale_description": "Shirt", "sale_deferred_months": null, "is_token_sale": false, "payme_signature": "b71e**************ca5a", "payme_transaction_id": "TRANDEMO-XXXXXXXX-XXXXXXXX-XXXXXXXX", "payme_transaction_total": "10000", "payme_transaction_card_brand": "Mastercard", "payme_transaction_auth_number": "0123456", "payme_transaction_voucher": "111111", "payme_transaction_emv_uid": null, "payme_transaction_acquirer": "PayMe", "payme_transaction_auth_source": "VoiceMail", "payme_transaction_card_issuer": "Isracard", "payme_transaction_credit_type": "RegularCredit", "buyer_name": "Israel Israeli", "buyer_email": "buyer@example.com", "buyer_phone": null, "buyer_card_mask": "532610******5846", "buyer_card_exp": "1230", "buyer_card_is_foreign": false, "buyer_social_id": "008336174", "installments": 1, "transaction_first_payment": 10000, "transaction_periodical_payment": 0, "transaction_arn": null, "sale_paid_date": "2026-11-09 10:16:40", "sale_release_date": null, "sale_3ds": false, "session": "Ab12Cd34", "redirect_url": null, "cancel_url": null } ``` ### 400 — Error `20`: a card-like number in a field other than `credit_card_number`. Error `367`: the sale has expired. (error) | Field | Type | Description | | --- | --- | --- | | `status_code` | integer | `1`: the request failed. | | `status_error_code` | integer | PayMe's error code. See [Errors](/payments/getting-started/errors). | | `status_error_details` | string | The error message, in the language you asked for. | | `status_additional_info` | string | Extra detail: usually the field at fault, the sale's current status, or the masked card number. | | `session` | string | PayMe's ID for this request. Quote it when you contact PayMe. | ```json { "status_code": 1, "status_error_details": "The sale has expired", "status_additional_info": "", "status_error_code": 367, "session": "Ab12Cd34" } ``` ### 429 — Error `998`: another call for this sale is still running, or too many requests. Wait, then check the sale before retrying. (error) | Field | Type | Description | | --- | --- | --- | | `status_code` | integer | `1`: the request failed. | | `status_error_code` | integer | PayMe's error code. See [Errors](/payments/getting-started/errors). | | `status_error_details` | string | The error message, in the language you asked for. | | `status_additional_info` | string | Extra detail: usually the field at fault, the sale's current status, or the masked card number. | | `session` | string | PayMe's ID for this request. Quote it when you contact PayMe. | ```json { "status_code": 1, "status_error_details": "Operation is not permitted", "status_additional_info": "Duplicated action detected, please retry later", "status_error_code": 998, "session": "Ab12Cd34" } ``` ### 500 — Request errors. `1`: a required field is missing (named in `status_additional_info`). `350`: no sale has this `payme_sale_id`. `305`: the sale isn't `initial` or `failed`. `354`, `355`, `356`: invalid CVV, card number or expiry. `37`: invalid `buyer_zip_code`. `351`: invalid `installments`. `2`: the sale isn't a card sale. `357`: `buyer_key` or `token` sent on a `token` sale. `600`, `604`, `605`: the saved card doesn't exist, is no longer active, or belongs to another seller. (error) | Field | Type | Description | | --- | --- | --- | | `status_code` | integer | `1`: the request failed. | | `status_error_code` | integer | PayMe's error code. See [Errors](/payments/getting-started/errors). | | `status_error_details` | string | The error message, in the language you asked for. | | `status_additional_info` | string | Extra detail: usually the field at fault, the sale's current status, or the masked card number. | | `session` | string | PayMe's ID for this request. Quote it when you contact PayMe. | ```json { "status_code": 1, "status_error_details": "Cannot perform action due to an incorrect status", "status_additional_info": "completed", "status_error_code": 305, "session": "Ab12Cd34" } ```