Quickstart

Your first sale in the sandbox: you will create a sale, pay it as a buyer, receive PayMe's callback, and refund it. Every field below comes from the endpoint pages linked in each step.

You need:

⚠ TO CONFIRM: How does a developer get sandbox credentials (seller_payme_id/MPL, payme_client_key, public key) — self-service sign-up, an account manager, or an email to support? [Q5]

Step 1 — Create the sale

Endpoint: POST /generate-sale. No payment happens yet.

curl -X POST https://sandbox.payme.io/api/generate-sale \
  -H 'Content-Type: application/json' \
  -d '{
    "seller_payme_id": "MPLDEMO-MPLDEMO-MPLDEMO-1234567",
    "sale_price": 1000,
    "currency": "ILS",
    "product_name": "Test order",
    "transaction_id": "order-1001",
    "installments": "1",
    "sale_callback_url": "https://your-server.example.com/payme/callback",
    "sale_return_url": "https://your-site.example.com/payment/success",
    "language": "en"
  }'
Field Meaning
seller_payme_id Your MPL. Required.
sale_price Price in minor units: 1000 = 10.00. Default allowed range 500–4000000, in every currency (so 500 is 5.00 ILS but 500 JPY). Required.
currency 3-letter ISO 4217 code, enabled on your account. Required.
product_name Short product description, up to 500 characters. Required.
transaction_id Your own order ID, for correlation with PayMe. Optional.
installments 1–12 fixed, or 103/106/109/112 to let the buyer choose up to 3/6/9/12.
sale_callback_url Where PayMe sends the server-to-server callback. Defaults to the merchant's settings.
sale_return_url Where the buyer is redirected after paying. Defaults to the merchant's settings.
language Payment page and error-message language. If omitted, messages are in Hebrew — always send "en" while integrating.

sale_price and installments accept a number or a numeric string (1000 or "1000", 1 or "1"). A non-numeric sale_price returns error 352; a non-numeric installments returns error 10. A decimal sale_price is rounded to whole minor units.

Successful response (for the request above):

{
  "status_code": 0,
  "sale_url": "https://preprod.paymeservice.com/sale/generate/XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX",
  "payme_sale_id": "XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX",
  "payme_sale_code": 12345678,
  "price": 1000,
  "transaction_id": "order-1001",
  "currency": "ILS"
}

Step 2 — Pay as the buyer

Open sale_url in a browser (or an IFRAME). Pay with a sandbox test card, for example:

Card number Expiry CVV Social ID
5326105300985846 12/30 658 008336174

This is a local Israeli card that accepts ILS only. Other cards, including cards that force a decline, are on Test Cards and Payment Methods.

You can pre-fill buyer details by appending query parameters to sale_url, for example ?first_name=First&last_name=Last&email=test@example.com. Card fields cannot be pre-filled.

Use sale_url exactly as returned.

⚠ TO CONFIRM: The sale_url host is most likely sandbox.payme.io in the sandbox and live.payme.io in production; the preprod.paymeservice.com host in the response example above appears to be a pre-production host. Please confirm, so the example can be corrected. [Q38]

To try a decline, pay with 4000000000000002: the result is HTTP 200 with status_code: 1 and error 20004. Other decline cards are on Environments.

After a successful payment the buyer is redirected (GET) to your sale_return_url with the sale details as query parameters:

https://your-site.example.com/payment/success?payme_status=success&payme_signature=75e99dbcb25cdfbe1c62f0b9376f4144&payme_sale_id=XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX&payme_transaction_id=XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX&price=1000&currency=ILS&transaction_id=order-1001&is_token_sale=0

Use the redirect only to show the buyer a result page. Use the callback (step 3) to update your order.

Step 3 — Receive the callback

When the sale is paid, PayMe sends a POST with an x-www-form-urlencoded body to sale_callback_url. Key fields:

Field Example Meaning
notify_type sale-complete What happened. See Callbacks.
status_code 0 0 success, 1 error
payme_sale_id XXXXXXXX-… PayMe's sale ID
transaction_id order-1001 Your order ID
sale_status completed See Sale Statuses
price, currency 1000, ILS Amount in minor units and currency
payme_signature 75e99dbcb25cdfbe1c62f0b9376f4144 Signature

To test your handler before you have a sandbox account, send yourself a callback with the documented shape:

curl -X POST https://your-server.example.com/payme/callback \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'status_code=0' \
  --data-urlencode 'notify_type=sale-complete' \
  --data-urlencode 'sale_created=2016-01-01 15:15:15' \
  --data-urlencode 'transaction_id=order-1001' \
  --data-urlencode 'payme_sale_id=XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX' \
  --data-urlencode 'payme_sale_code=12345678' \
  --data-urlencode 'payme_transaction_id=XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX' \
  --data-urlencode 'price=1000' \
  --data-urlencode 'currency=ILS' \
  --data-urlencode 'sale_status=completed' \
  --data-urlencode 'installments=1' \
  --data-urlencode 'is_token_sale=0' \
  --data-urlencode 'payme_signature=75e99dbcb25cdfbe1c62f0b9376f4144'

Your handler should:

  1. Reply 200 within 5 seconds. Any status below 400 counts as delivered; anything else, or a timeout, makes PayMe retry — up to 3 attempts in total, then the callback is dropped.
  2. Ignore repeats — de-duplicate on notify_type + payme_sale_id + payme_transaction_id.
  3. Verify payme_signature — the recipe is on Callbacks (section "Verifying a callback").
  4. Confirm the sale before fulfilling — treat the callback's status and amount as a notification, not proof of payment: call POST /get-sales with sale_payme_id and check sale_status and sale_price.

Step 4 — Refund the sale

Endpoint: POST /refund-sale. Omit sale_refund_amount for a full refund; send it for a partial refund (minimum 500). You can refund several times as long as the total does not exceed the sale amount.

curl -X POST https://sandbox.payme.io/api/refund-sale \
  -H 'Content-Type: application/json' \
  -d '{
    "seller_payme_id": "MPLDEMO-MPLDEMO-MPLDEMO-1234567",
    "payme_sale_id": "SALEDEMO-XXXXXXXX-XXXXXXXX-XXXXXXXX",
    "sale_refund_amount": 500,
    "language": "en"
  }'

payme_client_key is not needed here: a merchant can refund with seller_payme_id alone. Partners (platforms) may also send their payme_client_key, in which case the seller must belong to that partner.

Successful response (abridged):

{
  "status_code": 0,
  "status_error_code": 0,
  "payme_status": "success",
  "sale_status": "partial-refund",
  "sale_refund_buffer": 500,
  "payme_transaction_total": 500,
  "payme_transaction_id": "TRANDEMO-XXXXXXXX-XXXXXXXX-XXXXXXXX",
  "payme_signature": "b71e**************ca5a"
}

PayMe also sends a callback with notify_type refund to the callback URL; its payme_transaction_total is the amount of this refund and sale_refund_buffer the amount still refundable.

Do not blindly retry a refund that timed out: a repeated partial refund runs again and refunds a second time. Read Idempotency and retries first.

Next steps