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:
seller_payme_id (MPL) — see Authentication. Keep it on your server: on its own it authenticates seller-level calls; POST requests, for the callback. It may not be localhost or a private IP address; use HTTPS.⚠ 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]
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"
}
status_code 0 means success, 1 means error. payme_sale_id (PayMe's sale ID) next to your transaction_id. You need it to refund.status_code is 1, read status_error_code and status_error_details — see Errors. Errors usually come back with HTTP 500, so check status_code, not the HTTP status. transaction_id: sending this request twice creates two sales.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_urlhost is most likelysandbox.payme.ioin the sandbox andlive.payme.ioin production; thepreprod.paymeservice.comhost 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¤cy=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.
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:
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. notify_type + payme_sale_id + payme_transaction_id. payme_signature — the recipe is on Callbacks (section "Verifying a callback").POST /get-sales with sale_payme_id and check sale_status and sale_price.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.