Create a multi-method checkout sale
- Sandbox:
POST https://sandbox.payme.io/api/generate-sale - Production:
POST https://live.payme.io/api/generate-sale
Credentials
- Request body field
seller_payme_id(required): The seller's MPL. Send it in the JSON body:generate-saledoesn't read thePayMe-Merchant-Keyheader, so a request without a body MPL returns error1. Partners may sendseller_idwithpayme_client_keyinstead. - Request body field
payme_client_key(optional): Partners only: your partner key (or send thePayMe-Partner-Keyheader). Withseller_payme_id, the seller must belong to you, otherwise error20.
Overview
Creates a sale whose payment page lets the buyer choose any payment method enabled on the account: card, Bit, Apple Pay, Google Pay and others. Send sale_payment_method: multi; without it the sale is created as credit-card. Show the returned sale_url to the buyer in an iframe or a redirect.
POST https://sandbox.payme.io/api/generate-sale (production: https://live.payme.io/api/generate-sale), with a JSON body (Content-Type: application/json).
| To | Send |
|---|---|
| Charge now (J4) | sale_type: sale (default) |
| Authorize now, capture later (J5, up to 168 hours) | sale_type: authorize; then capture-sale |
| Let many buyers pay one link | sale_type: template (Template sales) |
This page lists the fields that matter on a multi-method page. Every other generate-sale field, and the sale_url validity rules, are on Create a sale.
Credentials
Send seller_payme_id (the MPL) in the JSON body: this endpoint doesn't read the PayMe-Merchant-Key header, so a request without a body MPL returns error 1. Partners add payme_client_key (or the PayMe-Partner-Key header) and may name the seller by seller_id instead. See Authentication.
Rules for every request
- Amounts are in minor units (
1000= 10.00). - Never put card numbers in any field. A value (other than
transaction_idandorder_number) that contains a 14–19-digit number passing the card checksum is refused with error20(HTTP 400), "<field> contains invalid data". - Don't send the legacy
pricefield: it is in major units and, when numeric, overridessale_price. - PayMe doesn't de-duplicate
transaction_id: every call creates a new sale. See Idempotency and Retries. - Errors return
status_code: 1withstatus_error_code, most with HTTP 500. See Errors.
Callbacks
When the sale is paid, PayMe sends a POST with an application/x-www-form-urlencoded body to sale_callback_url. The notification types and fields are on Callbacks.
Parameters
This endpoint takes no path, query or header parameters.
Request body
Content type: application/json
| Field | Type | Required | Description |
|---|---|---|---|
seller_payme_id |
string | yes | The seller's MPL. Send it in the JSON body: generate-sale doesn't read the PayMe-Merchant-Key header, so a request without a body MPL returns error 1. Partners may send seller_id with payme_client_key instead. |
payme_client_key |
string | no | Partners only: your partner key (or send the PayMe-Partner-Key header). With seller_payme_id, the seller must belong to you, otherwise error 20. |
seller_id |
string | no | Partners only: your own ID for the seller, set in create-seller, sent instead of seller_payme_id. Requires payme_client_key. |
sale_payment_method |
string | yes | Required for this page: multi. The page lists every payment method enabled on the account. Without it the sale is created as credit-card. |
sale_price |
integer | yes | Sale amount in minor units: 50.75 is sent as 5075. The default allowed range is 500–4000000, the same in every currency; PayMe can set a different range for a partner. A missing, non-numeric or out-of-range value returns error 352. Decimals are rounded. |
currency |
string | yes | Sale currency, a 3-letter ISO 4217 code such as ILS, enabled on the account (otherwise error 252). Required for sale and authorize; a token or template sale without it uses the account's default currency. |
product_name |
string | yes | Short description of the product or service, up to 500 characters. Shown to the buyer, and on the invoice when the invoicing service is active. Missing returns error 353. |
transaction_id |
string | no | Your own order reference, up to 50 characters. PayMe returns it in responses and callbacks but doesn't check it for uniqueness. |
installments |
string | no | Number of payments. 1 (default) or 0: one payment. 2–12: that fixed number. 102–112: the buyer chooses on the page, up to the last two digits (106 = up to 6). More than one installment is ILS only (312) and works only with credit-card or multi (other methods return 351). On a multi page that lets the buyer choose, a buyer who pays with Apple Pay or Google Pay pays in one payment. Fixed values above 12 are accepted when the sale is created, but the payment fails unless PayMe has enabled more installments on your account. A non-numeric value returns 10, any other unaccepted value 351, and an ILS price lower than the number of installments 358. |
sale_type |
string | no | sale (default) – charge now (J4). authorize – reserve the amount for up to 168 hours, then capture it with capture-sale (J5). template – one link that many buyers can pay. The full list is on Sale Types; any other value returns 357. |
market_fee |
number | no | The partner's (marketplace's) fee: a percentage of the sale price, VAT included, from 0 to 60. It is added on top of PayMe's fees and transferred to the marketplace once a month. Default: the seller's market fee set at create-seller. A non-numeric value returns 10, a negative one 304, and more than 60 308. Ignored for sellers paid directly. |
sale_callback_url |
string | no | Where PayMe sends server-to-server callbacks for this sale, as a form-encoded POST; see Callbacks. If omitted, PayMe uses your partner's default callback URL, if one is set; a seller has no dashboard setting for it, so send it on every call. Must be a public address: localhost, private or loopback IP addresses and IPv6 addresses are refused with error 21, which fails the whole call. |
sale_return_url |
string | no | Where PayMe redirects the buyer (the iframe or the full page) after a successful payment, with the sale details as query parameters; see Hosted Payment Page options. If omitted, your partner's default return URL is used, if one is set. Same address rules as sale_callback_url (error 21). |
cancel_url |
string | no | Where to send the buyer when 3D Secure authentication fails, instead of back to the payment page. Also the PayPal cancel address. Must be a public URL (error 21). |
sale_send_notification |
boolean | no | true: PayMe sends the buyer a payment request with the payment link, by email to sale_email and by SMS to sale_mobile. Default false. |
sale_email |
string | no | Buyer's email. Pre-fills the payment page and receives the payment request when sale_send_notification is true. |
sale_mobile |
string | no | Buyer's mobile number. Pre-fills the payment page and receives the SMS payment request when sale_send_notification is true and the SMS service is active on the account. |
sale_name |
string | no | Buyer's full name. Pre-fills the payment page (split at the first space into first and last name) and is used in notifications. |
sale_send_creation_callback |
boolean | no | true: PayMe also sends a sale-create callback, with sale_url, as soon as the sale is created. Default false. |
sale_expiry_seconds |
integer | no | How many seconds the sale stays payable after it is created. After that, the payment page answers HTTP 403 and paying the sale fails with error 367. Without it, sale_url has no fixed expiry. |
capture_buyer |
string | no | 1 or true to save the buyer's card as a token after the payment; the token arrives as buyer_key in the callback. Omit it, or send 0, to skip. Works with credit-card, apple-pay, il-direct-debit and multi (other methods return 4). Can't be combined with buyer_key (601). |
buyer_is_private |
boolean | no | With capture_buyer or a token sale: true ties the token to this seller, so get-buyer-key works with the seller's MPL. Without it the token is account-level: any seller of the same partner can charge it, and a get-buyer-key call that sends seller_payme_id fails with error 603. |
buyer_perform_validation |
boolean | no | With capture_buyer or a token sale: whether PayMe validates the card with the issuer before saving the token. Default true. Sending true without capture_buyer or a token sale returns 608. |
layout |
string | no | Payment page layout: dynamic (default), dynamic-loose (no social ID or CVV validation), qr-sms (Bit: QR code or SMS), token-capture (save a card without a charge; requires sale_type: token). Other values fall back to dynamic. |
language |
string | no | Language of the payment page and the error messages. Default he. he and en are fully supported; es, ru and ar are accepted, but messages and the payment page are then mostly in English. Case-insensitive; any other value, or an empty string, returns error 51. |
services |
array | no | Per-sale settings for services on the account, as objects {"name": "<service>", "settings": {...}}. For example [{"name": "invoice", "settings": {"active": false}}] skips the invoice for this sale, and [{"name": "3DSecure", "settings": {"active": true}}] forces 3D Secure. Each object needs settings (error 1). Unknown or inactive services are ignored. |
order_number |
string | no | Purchase order number, used for level 2 and level 3 card data. Up to 15 digits. |
items |
array | no | Line items of the sale, as an array of objects. If you send items, every item needs name, quantity, unit_price and total; an invalid item returns error 20 (HTTP 422) with the failing rules in status_additional_info. Item keys are case-insensitive. |
items[].name |
string | yes | Item name, 1–50 characters. |
items[].quantity |
integer | yes | Quantity, 0–999999. |
items[].unit_price |
integer | yes | Price of one unit, in minor units. |
items[].total |
integer | yes | Line total after discount, in minor units, 0–9000000000. |
items[].unit_measurement |
string | no | Unit of measurement, for example kg. |
items[].discount_total |
number | no | Discount on this line, in minor units, sent as a negative number. |
items[].description |
string | no | Item description, up to 150 characters. |
items[].product_code |
string | no | Your catalog code for the item, up to 100 characters. |
items[].commodity_code |
number | no | Numeric commodity code of the item. |
items[].custom1 |
string | no | Free text for your own use, up to 100 characters. |
items[].custom2 |
string | no | Free text for your own use, up to 100 characters. |
fees |
object | no | Amounts included in the payment, for level 2 and level 3 card data. Each is in minor units, up to 12 digits. |
fees.tax |
number | no | Tax included in the payment. |
fees.duty |
number | no | International duties included in the payment. |
fees.discount |
number | no | Total discount given on the payment. |
fees.shipping |
number | no | Shipping cost included in the payment. |
shipping_details |
object | no | Where the order is shipped. Stored with the sale. |
shipping_details.name |
string | no | Addressee's full name or company name, up to 50 characters. |
shipping_details.email |
string | no | Addressee's email, up to 100 characters. |
shipping_details.phone |
string | no | Addressee's phone number, up to 50 characters. |
shipping_details.address |
object | no | The shipping address. |
shipping_details.address.line1 |
string | no | First line of the shipping address. |
shipping_details.address.line2 |
string | no | Second line of the shipping address. |
shipping_details.address.postal_code |
string | no | Postal code of the shipping address. |
shipping_details.address.city |
string | no | City of the shipping address. |
shipping_details.address.state |
string | no | State or region of the shipping address. |
shipping_details.address.country |
string | no | Two-letter ISO 3166-1 country code, for example IL. Other values are ignored. |
billing_details |
object | no | The payer's billing details. Stored with the sale. |
billing_details.name |
string | no | Payer's full name or company name. |
billing_details.email |
string | no | Payer's email. |
billing_details.phone |
string | no | Payer's phone number. |
billing_details.address |
object | no | The billing address. |
billing_details.address.line1 |
string | no | First line of the billing address. |
billing_details.address.line2 |
string | no | Second line of the billing address. |
billing_details.address.postal_code |
string | no | Postal code of the billing address. |
billing_details.address.city |
string | no | City of the billing address. |
billing_details.address.state |
string | no | State or region of the billing address. |
billing_details.address.country |
string | no | Two-letter ISO 3166-1 country code, for example IL. Other values are ignored. |
Request example
{
"seller_payme_id": "MPLDEMO-MPLDEMO-MPLDEMO-1234567",
"sale_payment_method": "multi",
"sale_price": 1000,
"currency": "ILS",
"product_name": "Smartphone",
"transaction_id": "order-1001",
"installments": "1",
"sale_type": "sale",
"sale_callback_url": "https://your-server.example.com/payme/callback",
"sale_return_url": "https://your-site.example.com/payment/success",
"sale_name": "First Last",
"sale_email": "buyer@example.com",
"language": "en"
}
Code samples
curl
curl -X POST 'https://sandbox.payme.io/api/generate-sale' \
-H 'Content-Type: application/json' \
--data-raw '{
"seller_payme_id": "MPLDEMO-MPLDEMO-MPLDEMO-1234567",
"sale_payment_method": "multi",
"sale_price": 1000,
"currency": "ILS",
"product_name": "Smartphone",
"transaction_id": "order-1001",
"installments": "1",
"sale_type": "sale",
"sale_callback_url": "https://your-server.example.com/payme/callback",
"sale_return_url": "https://your-site.example.com/payment/success",
"sale_name": "First Last",
"sale_email": "buyer@example.com",
"language": "en"
}'
Node.js
const response = await fetch("https://sandbox.payme.io/api/generate-sale", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
"seller_payme_id": "MPLDEMO-MPLDEMO-MPLDEMO-1234567",
"sale_payment_method": "multi",
"sale_price": 1000,
"currency": "ILS",
"product_name": "Smartphone",
"transaction_id": "order-1001",
"installments": "1",
"sale_type": "sale",
"sale_callback_url": "https://your-server.example.com/payme/callback",
"sale_return_url": "https://your-site.example.com/payment/success",
"sale_name": "First Last",
"sale_email": "buyer@example.com",
"language": "en"
}),
});
console.log(await response.text());
Python
import requests
response = requests.post(
"https://sandbox.payme.io/api/generate-sale",
json={
"seller_payme_id": "MPLDEMO-MPLDEMO-MPLDEMO-1234567",
"sale_payment_method": "multi",
"sale_price": 1000,
"currency": "ILS",
"product_name": "Smartphone",
"transaction_id": "order-1001",
"installments": "1",
"sale_type": "sale",
"sale_callback_url": "https://your-server.example.com/payme/callback",
"sale_return_url": "https://your-site.example.com/payment/success",
"sale_name": "First Last",
"sale_email": "buyer@example.com",
"language": "en",
},
)
print(response.text)
PHP
<?php
$body = <<<'BODY'
{
"seller_payme_id": "MPLDEMO-MPLDEMO-MPLDEMO-1234567",
"sale_payment_method": "multi",
"sale_price": 1000,
"currency": "ILS",
"product_name": "Smartphone",
"transaction_id": "order-1001",
"installments": "1",
"sale_type": "sale",
"sale_callback_url": "https://your-server.example.com/payme/callback",
"sale_return_url": "https://your-site.example.com/payment/success",
"sale_name": "First Last",
"sale_email": "buyer@example.com",
"language": "en"
}
BODY;
$ch = curl_init('https://sandbox.payme.io/api/generate-sale');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Responses
200 — Sale created (success)
| Field | Type | Description |
|---|---|---|
status_code |
integer | 0 success, 1 error. |
sale_url |
string | PayMe's payment page for this sale. Show it to the buyer in an iframe or a redirect, exactly as returned. It stays payable while the sale is initial or failed, until sale_expiry_seconds passes if you sent it. |
payme_sale_id |
string | PayMe's sale ID. Store it: refunds, captures and queries use it. |
payme_sale_code |
integer | Short numeric sale code, for display only. |
price |
integer | Sale amount in minor units (100 for a token sale). |
transaction_id |
string | Your order reference, as sent. |
currency |
string | Sale currency (ISO 4217). |
sale_payment_method |
string | Payment method of the sale, for example credit-card or multi. |
session |
string | Request ID. Quote it when you contact PayMe. |
{
"status_code": 0,
"session": "AtsJ0as5",
"sale_url": "https://sandbox.payme.io/sale/generate/SALE1700-000000AA-EXAMPLE1-SALE0001",
"payme_sale_id": "SALE1700-000000AA-EXAMPLE1-SALE0001",
"payme_sale_code": 12345678,
"price": 1000,
"transaction_id": "order-1001",
"currency": "ILS",
"sale_payment_method": "multi"
}
500 — Request refused. Most request errors return HTTP 500 with status_code: 1; some return 400, 403, 422 or 429. See Errors. (error)
| Field | Type | Description |
|---|---|---|
status_code |
integer | 1 for an error. |
status_error_code |
integer | PayMe's error code, for example 251 (seller not found) or 352 (invalid price). |
status_error_details |
string | The error message, in the requested language (Hebrew by default). |
status_additional_info |
string | Extra detail, usually the name of the field at fault. |
session |
string | Request ID. Quote it when you contact PayMe. |
{
"status_code": 1,
"status_error_details": "Seller was not found",
"status_additional_info": "seller_payme_id",
"status_error_code": 251,
"session": "AtsJ0as5"
}