Save a card (token sale)

Credentials

Overview

Saves the buyer's card as a token (buyer_key) for later server-to-server charges. Send sale_type: token to save the card without charging (PayMe sets the price to 100, which is not charged), or capture_buyer: 1 on a normal sale to charge and save. The token arrives as buyer_key in the callback; you can also read it with get-buyer-key.

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
Save the card without charging sale_type: token
Charge and save the card sale_type: sale (default) and capture_buyer: 1
Save a card on a page that can be opened only once sale_type: token, layout: token-capture and sale_should_be_opened_once: true
Charge a saved card later buyer_key on a new generate-sale; see Create a sale

To charge and save, send the same request as the example with "sale_type": "sale", your real sale_price and "capture_buyer": 1.

Rules:

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.

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_type string no token – save the card without charging (the price is set to 100). sale (default) – charge; add capture_buyer: 1 to save the card too. Token capture works with credit-card, apple-pay, il-direct-debit and multi (other methods return 4). The full list is on Sale Types.
sale_price integer yes Amount in minor units. Required, but for a token sale any numeric value works: PayMe replaces it with 100 and charges nothing. A missing or non-numeric value returns 352. For a charge-and-save sale, the default allowed range is 500–4000000.
currency string no Sale currency, a 3-letter ISO 4217 code. Optional for a token sale (the account's default currency is used); required to charge.
product_name string yes Short description shown to the buyer and in the seller's records, up to 500 characters. Required, also for token sales (missing returns 353).
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.
sale_payment_method string no Payment method; see Available Payment Methods. Default credit-card. Send multi to let the buyer choose among every method enabled on the account. Case-insensitive. An unknown value returns 24; a method not enabled on the account returns 720 with the method name; bacs needs GBP and sepa needs EUR (320). Send a string: an array returns 368 (HTTP 400).
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.
sale_should_be_opened_once boolean no true: with layout: token-capture, the page can be opened only once. Ignored otherwise.
buyer_key string no To charge a saved token later, on a new generate-sale: the call charges it at once, with no payment page. Can't be combined with capture_buyer (601) or sale_type: token (602).
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.
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).
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.
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.

Request example

{
  "seller_payme_id": "MPLDEMO-MPLDEMO-MPLDEMO-1234567",
  "sale_type": "token",
  "sale_price": 100,
  "currency": "ILS",
  "product_name": "Save card",
  "buyer_is_private": true,
  "sale_callback_url": "https://your-server.example.com/payme/callback",
  "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_type": "token",
  "sale_price": 100,
  "currency": "ILS",
  "product_name": "Save card",
  "buyer_is_private": true,
  "sale_callback_url": "https://your-server.example.com/payme/callback",
  "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_type": "token",
    "sale_price": 100,
    "currency": "ILS",
    "product_name": "Save card",
    "buyer_is_private": true,
    "sale_callback_url": "https://your-server.example.com/payme/callback",
    "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_type": "token",
        "sale_price": 100,
        "currency": "ILS",
        "product_name": "Save card",
        "buyer_is_private": True,
        "sale_callback_url": "https://your-server.example.com/payme/callback",
        "language": "en",
    },
)

print(response.text)

PHP

<?php

$body = <<<'BODY'
{
  "seller_payme_id": "MPLDEMO-MPLDEMO-MPLDEMO-1234567",
  "sale_type": "token",
  "sale_price": 100,
  "currency": "ILS",
  "product_name": "Save card",
  "buyer_is_private": true,
  "sale_callback_url": "https://your-server.example.com/payme/callback",
  "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 — Token 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": 100,
  "transaction_id": null,
  "currency": "ILS",
  "sale_payment_method": "credit-card"
}

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"
}