payeer API documentation

Complete API reference for integrating with payeer

API Credentials

Every merchant account has three credentials in Merchant Settings. Use them on your server — never in browser or mobile client code.

App ID

Your merchant account identifier. Send it as the appid parameter when you create orders and query orders.

API Key

Your secret signing key. It is not sent as a request parameter. Use it only on your server to:

Key

A separate query credential used with your App ID for read-only order lookups via GET /api/order. Pass it as the key query parameter together with appid.

Where to find them: Log in to the merchant portal and open Merchant Settings — App ID, API Key, and Key are shown with copy buttons. If you just registered, they are generated automatically when your account is created.

Quick Integration

Follow these steps to accept your first payment. Start in the Sandbox Playground with test credentials before using live keys.

API base URL

All endpoints are relative to your gateway origin (this deployment: https://payeer.online):

  • POST https://payeer.online/api/createorder — JSON API (recommended for server-side checkout)
  • GET …/api/createorder?… — hosted HTML checkout page (fastest to try; polls status and redirects to return_url)
  • GET …/api/order — query order status

Choose an integration mode

Mode When to use What you get
POST JSON Production checkout on your site or app backend JSON with redirectUrl / selectUrl — redirect the payer yourself
GET link Quick test or simple “Pay now” link HTML payment page (QR, polling, auto-redirect to return_url)

Steps

  1. Register or sign in — Create an account at /merchant/register or sign in at /merchant/login.
  2. Copy your credentials — Open Merchant Settings and copy your App ID, API Key, and Key (see API Credentials).
  3. Configure webhook delivery — Set a default callback URL in Settings or pass notify_url on each order. The saved URL is used for paid-order webhooks (see Callback Notification). If both are empty, no webhook is sent.
  4. Create an order — Call POST /api/createorder (JSON) or open GET /api/createorder (hosted page) with appid, clientip, action=createorder, amount, currency, paymentMethod, and sign. Set clientip to the public IP of the machine making the request (see Authentication).
  5. Redirect the customer to pay — From the JSON response, send the payer to redirectUrl or selectUrl (whichever is present). selectUrl means an extra step (pick a payment method or crypto) before paying; nextAction describes that step. If both are absent, use /payment/{paymentId} on this gateway.
  6. Handle the webhook — When payment succeeds, we POST to the order’s callback URL. Verify the signature with your API Key and respond with HTTP 200 and body success (see Callback Notification).
  7. Verify order status (optional) — When creating the order, set return_url with the {paymentId} placeholder (see Create Order), for example https://yoursite.com/success?paymentId={paymentId}. After payment, the customer is redirected to your page and {paymentId} is replaced with the real order ID. Read the paymentId query parameter from that URL, then call Query Order on your server to sync the latest status before showing a success message: GET /api/order?action=order&appid=YOUR_APPID&key=YOUR_KEY&paymentId=PAYMENT_ID_FROM_URL. Use the response fields status / status_str to update your local order. Webhooks remain the authoritative async notification; this pattern is for immediate confirmation when the payer lands on your return page.

End-to-end example (POST JSON)

Minimal server-side flow after you compute sign (see Signature):

// 1. Create order (run on your server; replace YOUR_* placeholders) const res = await fetch('https://payeer.online/api/createorder', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ appid, clientip, action: 'createorder', amount: 100, currency: 'CNY', paymentMethod: 'alipay', clientOrderId: 'ORDER-001', return_url, notify_url, sign, sign_type: 'MD5' }) }); const { data } = await res.json(); // 2. Redirect payer to checkout const checkoutUrl = data.redirectUrl || data.selectUrl || `/payment/${data.paymentId}`; // response.redirect(checkoutUrl) — your framework // 3. Webhook handler (express example) app.post('/api/notify', express.json(), (req, res) => { const expected = signStr(req.body, process.env.API_KEY); // same algorithm as #signature if (expected !== req.body.sign) return res.status(400).send('invalid sign'); // update your order if req.body.status_str === 'paid' res.status(200).send('success'); // must be the string "success" });
Tip: Test signatures and sample requests in the Sandbox Playground before going live.

Authentication

See API Credentials for your appid. Create-order requests also require clientip — the public IP of the client making the HTTP request (usually your backend server’s egress IP, or the payer’s IP when you proxy from the browser).

clientip must match the request IP. If they differ, /api/createorder returns HTTP 403 with Request IP does not match clientip. Behind a reverse proxy, ensure your server forwards the real client IP and pass that same value in clientip.
Security: Keep your API Key and Key secret. Never expose them in client-side code, mobile apps, or public repositories. Only your App ID and signed requests should leave your backend.

Signature Verification

All API requests that create or modify data require signature verification to ensure data integrity and prevent tampering.

How Signature Works

The signature is calculated using all request parameters (except sign and sign_type) and your API key (stored securely on the server).

Signature Algorithm:
  1. Collect all parameters except sign and sign_type
  2. Sort parameters alphabetically by key
  3. Join parameters as key=value pairs with &
  4. Append your API key to the string
  5. Calculate MD5 hash (lowercase) of the resulting string

Signature Parameters

Parameter Type Required Description
sign string Required MD5 signature of all parameters (calculated using your API key)
sign_type string Optional Signature type, currently only MD5 is supported (default: MD5)
Important: The signature must match exactly. If the signature verification fails, the request will be rejected with a 400 error. Sign the flat request fields sent to /api/createorder (not a nested JSON object). Empty strings are included; omit only null / undefined fields.

Worked example (createorder)

Given API Key 42ba8e8f-7cbb-4bf9-ba2a-57904f3d9451 and these parameters (before adding sign):

Signing plaintext (sorted key=value, joined with &), then append API Key and MD5:

action=createorder&amount=100&appid=YOUR_APPID&clientOrderId=YOUR_ORDER_ID_123&clientip=127.0.0.1&currency=CNY&description=Test order&notify_url=https://example.com/api/notify&paymentMethod=alipay&return_url=https://example.com/payment/success?paymentId={paymentId}42ba8e8f-7cbb-4bf9-ba2a-57904f3d9451 sign = 9bb303e3116d862fbeb23bd8a8a8b07d

sign_type is sent in the request but excluded from the signature. Numeric amount in JSON is signed as sent (e.g. 100, not 100.00).

Code Examples

Calculate sign on your server using the same flat parameters you send in the request:

import hashlib API_KEY = 'YOUR_API_KEY' def sign_createorder(params: dict) -> str: filtered = { k: v for k, v in params.items() if k not in ('sign', 'sign_type') and v is not None } plain = '&'.join(f'{k}={filtered[k]}' for k in sorted(filtered)) return hashlib.md5((plain + API_KEY).encode('utf-8')).hexdigest().lower() payload = { 'appid': 'YOUR_APPID', 'clientip': '127.0.0.1', 'action': 'createorder', 'amount': 100, 'currency': 'CNY', 'paymentMethod': 'alipay', 'description': 'Test order', 'clientOrderId': 'YOUR_ORDER_ID_123', 'return_url': 'https://example.com/payment/success?paymentId={paymentId}', 'notify_url': 'https://example.com/api/notify', } payload['sign'] = sign_createorder(payload) payload['sign_type'] = 'MD5'
const crypto = require('crypto'); const API_KEY = 'YOUR_API_KEY'; function signCreateorder(params) { const filtered = {}; for (const [k, v] of Object.entries(params)) { if (k === 'sign' || k === 'sign_type') continue; if (v === null || v === undefined) continue; filtered[k] = v; } const plain = Object.keys(filtered).sort() .map((k) => `${k}=${filtered[k]}`) .join('&'); return crypto.createHash('md5').update(plain + API_KEY).digest('hex').toLowerCase(); } const payload = { appid: 'YOUR_APPID', clientip: '127.0.0.1', action: 'createorder', amount: 100, currency: 'CNY', paymentMethod: 'alipay', description: 'Test order', clientOrderId: 'YOUR_ORDER_ID_123', return_url: 'https://example.com/payment/success?paymentId={paymentId}', notify_url: 'https://example.com/api/notify', }; payload.sign = signCreateorder(payload); payload.sign_type = 'MD5';
<?php $apiKey = 'YOUR_API_KEY'; function sign_createorder(array $params, string $apiKey): string { unset($params['sign'], $params['sign_type']); $params = array_filter($params, fn($v) => $v !== null); ksort($params); $plain = implode('&', array_map( fn($k) => $k . '=' . $params[$k], array_keys($params) )); return md5($plain . $apiKey); } $payload = [ 'appid' => 'YOUR_APPID', 'clientip' => '127.0.0.1', 'action' => 'createorder', 'amount' => 100, 'currency' => 'CNY', 'paymentMethod' => 'alipay', 'description' => 'Test order', 'clientOrderId' => 'YOUR_ORDER_ID_123', 'return_url' => 'https://example.com/payment/success?paymentId={paymentId}', 'notify_url' => 'https://example.com/api/notify', ]; $payload['sign'] = sign_createorder($payload, $apiKey); $payload['sign_type'] = 'MD5';

Create Order

Create a payment order. The response includes checkout URLs (redirectUrl / selectUrl) and/or a QR image URL depending on the payment method.

POST /api/createorder Requires Auth

Send a JSON body with Content-Type: application/json. Returns JSON with checkout URLs for your server to redirect the payer.

Request Parameters

Parameter Type Required Description
appid string Required Your application ID
clientip string Required Your client IP address
action string Required Must be createorder
amount number Required Order amount (e.g., 100.00)
currency string Required Currency code: CNY, USD, or BDT (use BDT with eps or paystation)
paymentMethod string Required Payment method (see Payment Methods section)
sign string Required MD5 signature (see Signature section)
sign_type string Optional Signature type (default: MD5)
description string Optional Order description
customerName string Optional Customer name
customerEmail string Optional Customer email
customerPhone string Optional Customer phone number
freekassaSystemId integer Optional When paymentMethod=freekassa: FreeKassa payment system ID (i). Omit to defer: response includes selectUrl and nextAction=freekassa_select for payer to choose method and FX quote. If set, initializes FreeKassa immediately. Confirm later via POST /api/freekassa/confirm.
allowedPaymentMethods string Optional When paymentMethod=select: comma-separated gateway codes to show on the payer selection page (e.g. alipay,wxpay,freekassa). Omit to show all methods enabled for the order currency and merchant account. USD orders include balance (logged-in customer account balance) by default; exclude with e.g. allowedPaymentMethods=alipay,wxpay. Included in signature.
lang string Optional Locale for the payer selection page UI (e.g. en, zh, es). Default en. When not en, selectUrl uses a locale path prefix (e.g. /zh/payment/{orderId}?step=select). Included in signature when provided.
return_url string Optional Return URL after payment completion (will redirect automatically if provided). You can use {paymentId} placeholder in the URL, which will be automatically replaced with the actual payment ID when redirecting. Example: https://example.com/success?paymentId={paymentId}
notify_url string Optional Webhook URL for this order. If omitted, the default callback URL from Merchant Settings is used. If both are empty, no webhook is sent for that order.
clientOrderId string Optional Client's own order identifier. Saved and returned in responses. When provided, duplicate create requests for the same merchant while the order is still pending or ready return the existing order (idempotent; safe to refresh the GET payment link). After paid, failed, or cancelled, a new order may be created with the same clientOrderId.
Important Notes:
  • IP Address Verification: The clientip parameter must match the actual request IP address, otherwise the request will be rejected (403 error).
  • Signature Verification: All requests must include a valid MD5 signature. Signature calculation errors will cause the request to fail (400 error).
  • Return URL Placeholder: You can use {paymentId} placeholder in return_url. The system will automatically replace it with the actual payment ID when redirecting after payment completion.
  • Callback URL: Per-order notify_url overrides Settings; otherwise the Settings default is stored on the order. Webhooks are only sent when the saved URL is non-empty.
  • Idempotent clientOrderId: Repeating POST or refreshing the GET payment URL with the same clientOrderId does not create another order while status is pending or ready.

Request Example

Success Response

Response fields (data)

Field Description
paymentId / orderId Gateway order identifier (same value). Use for Query Order and return_url placeholder.
redirectUrl URL to send the payer to pay immediately (gateway page, external PSP, or hosted checkout).
selectUrl Present when the payer must choose a method first (paymentMethod=select, deferred FreeKassa/NOWPayments). Often equals redirectUrl in that case.
nextAction Hint when selectUrl is used: e.g. payment_method_select, freekassa_select, nowpayments_select.
qrImageUrl QR code image URL when applicable (may be null for redirect-only methods).
status / statusString Order state — see Order Status. Balance payments may return paid immediately.

Redirect rule: redirectUrl || selectUrl || /payment/{paymentId}.

Error Response

Signature Verification: This endpoint requires signature verification. The signature must be calculated using all parameters (except sign and sign_type) and your API key. See the Signature section for details.
GET /api/createorder Requires Auth

Create a new payment order and receive an HTML payment page. The page will automatically poll the order status every 4 seconds, timeout after 3 minutes, and automatically redirect to return_url when payment is completed.

Request Parameters

Note: All parameters are passed as query parameters (URL parameters). Parameters are the same as POST request above.

Parameter Type Required Description
appid string Required Your application ID
clientip string Required Your client IP address
action string Required Must be createorder
amount number Required Order amount (e.g., 100.00)
currency string Required Currency code: CNY, USD, or BDT (use BDT with eps or paystation)
paymentMethod string Required Payment method (see Payment Methods section)
sign string Required MD5 signature (see Signature section)
sign_type string Optional Signature type (default: MD5)
description string Optional Order description
customerName string Optional Customer name
customerEmail string Optional Customer email
customerPhone string Optional Customer phone number
freekassaSystemId integer Optional When paymentMethod=freekassa: FreeKassa payment system ID (i). Omit to defer: response includes selectUrl and nextAction=freekassa_select for payer to choose method and FX quote. If set, initializes FreeKassa immediately. Confirm later via POST /api/freekassa/confirm.
allowedPaymentMethods string Optional When paymentMethod=select: comma-separated gateway codes to show on the payer selection page (e.g. alipay,wxpay,freekassa). Omit to show all methods enabled for the order currency and merchant account. USD orders include balance (logged-in customer account balance) by default; exclude with e.g. allowedPaymentMethods=alipay,wxpay. Included in signature.
lang string Optional Locale for the payer selection page UI (e.g. en, zh, es). Default en. When not en, selectUrl uses a locale path prefix (e.g. /zh/payment/{orderId}?step=select). Included in signature when provided.
return_url string Optional Return URL after payment completion (page will automatically redirect after 1 second if payment succeeds). You can use {paymentId} placeholder in the URL, which will be automatically replaced with the actual payment ID when redirecting. Example: https://example.com/success?paymentId={paymentId}
notify_url string Optional Webhook URL for this order. If omitted, the default callback URL from Merchant Settings is used. If both are empty, no webhook is sent.
clientOrderId string Optional Client's own order identifier. Saved and returned in responses. When provided, duplicate create requests for the same merchant while the order is still pending or ready return the existing order (idempotent; safe to refresh the GET payment link). After paid, failed, or cancelled, a new order may be created with the same clientOrderId.

Request Example

GET /api/createorder?appid=YOUR_APPID&clientip=127.0.0.1&action=createorder&amount=100¤cy=CNY&paymentMethod=alipay&description=Test+order&clientOrderId=YOUR_ORDER_ID_123&return_url=https%3A%2F%2Fexample.com%2Fsuccess%3FpaymentId%3D%7BpaymentId%7D¬ify_url=https://example.com/api/notify&sign=CALCULATED_SIGNATURE&sign_type=MD5
Important Notes:
  • IP Address Verification: The clientip parameter must match the actual request IP address, otherwise the request will be rejected (403 error).
  • Signature Verification: All requests must include a valid MD5 signature. Signature calculation errors will cause the request to fail (400 error).
  • Return URL Placeholder: You can use {paymentId} placeholder in return_url. The system will automatically replace it with the actual payment ID when redirecting after payment completion.
  • Callback URL: Per-order notify_url overrides Settings; otherwise the Settings default is stored on the order.
  • Idempotent clientOrderId: Refreshing this payment URL (or repeating the request) with the same clientOrderId does not create another order while status is pending or ready.

Response

Returns an HTML payment page that includes:

  • Order information display
  • QR code for payment (if order is ready)
  • Automatic status polling (every 4 seconds)
  • 3-minute countdown timer
  • Automatic redirect to return_url when payment is completed
Page Features:
  • Automatically polls order status every 4 seconds
  • Shows a 3-minute countdown timer
  • Automatically redirects to return_url when payment is completed (after 1 second delay)
  • Handles timeout after 3 minutes
  • Displays QR code for payment scanning
Signature Verification: This endpoint requires signature verification. The signature must be calculated using all parameters (except sign and sign_type) and your API key. See the Signature section for details.

Query Order

Query single order details or list multiple orders.

Typical use: after the payer returns via return_url with paymentId={paymentId}, call this endpoint with the resolved paymentId to sync order status on your success page (see Quick Integration step 7).

GET /api/order Requires Auth

Request Parameters

Parameter Type Required Description
appid string Required Your application ID
key string Required Your key (UUID format)
action string Required order (single) or orders (list)
paymentId string Required if action=order Payment ID to query
page number Optional Page number (default: 1, only for action=orders)
limit number Optional Items per page (max: 50, default: 10, only for action=orders)

Request Example

GET /api/order?action=order&appid=YOUR_APPID&key=YOUR_KEY&paymentId=abc123def456

Single Order Response

Order List Response

Callback Notification

When an order status changes to paid, the system will automatically send a callback notification to your specified URL.

Callback URL configuration:
  • Pass notify_url when creating an order to override the per-order webhook URL
  • If omitted, the default callback URL from Merchant Settings is saved on the order
  • Webhooks are sent only when the order has a non-empty saved callback URL (from either source)

Callback Request

The system sends a POST request to your callback URL with the following parameters:

Parameter Type Description
paymentId string Unique payment identifier
amount string Order amount (as string, e.g., "2.2")
currency string Currency code: CNY, USD, or BDT (use BDT with eps or paystation)
status string Order status code: "2" (paid)
status_str string Order status string: "paid"
paymentMethod string Payment method used: alipay, wxpay, crypto, eps, or paystation
description string Order description (if provided)
completedTime string Payment completion time in ISO 8601 format (e.g., "2025-12-01T02:32:05.877Z")
createdAt string Order creation time in ISO 8601 format (e.g., "2025-12-01T02:31:43.997Z")
clientOrderId string Client order ID (if provided when creating the order)
sign string MD5 signature for verifying the callback authenticity
sign_type string Signature type: MD5

Callback Example

Signature Verification

You must verify the callback signature to ensure the request is authentic. The signature is calculated using the same algorithm as API requests:

  1. Collect all parameters except sign and sign_type
  2. Sort parameters alphabetically by key
  3. Join parameters as key=value pairs with &
  4. Append your API key to the string
  5. Calculate MD5 hash (lowercase) of the resulting string
  6. Compare the calculated signature with the sign parameter
Security: Always verify the callback signature before processing the payment. Do not trust callbacks without valid signatures.

Callback Response

Your callback endpoint must return a specific response to acknowledge successful receipt:

  • Success: Return HTTP 200 status code with response body containing the string "success" (case-insensitive). The response body must be exactly "success" (e.g., "success", "SUCCESS", or "Success"). Any other response will be considered a failure and trigger retry.
  • Failure: Return any non-200 status code, or return HTTP 200 with a response body that is not "success" (case-insensitive) will trigger retry
Important: The callback is only considered successful when:
  1. HTTP status code is 200
  2. Response body (trimmed and case-insensitive) equals "success"

Examples of successful responses:

  • "success"
  • "SUCCESS"
  • "Success"

Examples of failed responses (will trigger retry):

  • {"code": 1, "message": "success"} ✗ (not the string "success")
  • "ok" ✗ (not "success")
  • "received" ✗ (not "success")
  • HTTP 500 or any non-200 status code ✗

Retry Mechanism

The system implements an automatic retry mechanism for failed callbacks:

  • Maximum attempts: 20 retries
  • Retry intervals: Exponential backoff (increasing delays between retries)
  • Retry conditions: Callbacks are retried if:
    • Your server returns a non-200 status code
    • Your server returns HTTP 200 but the response body is not "success" (case-insensitive)
    • The request fails (network error, timeout, etc.)
  • Success: Once your server returns HTTP 200 with response body "success" (case-insensitive), no further callbacks will be sent for that order
Best Practices:
  • Implement idempotency: Check if the order has already been processed before processing again
  • Verify the signature before processing
  • Return HTTP 200 with response body "success" immediately after receiving and validating the callback, then process the order asynchronously if needed
  • Log all callback requests for debugging and auditing
  • Use HTTPS for callback URLs to ensure secure transmission
  • Important: Ensure your callback endpoint returns exactly the string "success" (case-insensitive) for successful processing

Order Status Codes

Orders have the following status values:

Code String Description
0 pending Order created, saved locally
1 ready Order sent to payment provider, QR code generated
2 paid Payment completed successfully
3 failed Payment failed
4 cancelled Order cancelled

Payment Methods

Supported payment methods and their currency compatibility:

Method Code Supported Currencies Description
Alipay alipay CNY, USD Alipay mobile payment
WeChat Pay wxpay CNY, USD WeChat mobile payment
Heleket (Crypto) heleket USD Redirect to Heleket payment page. Webhook: POST /api/gatewaynotification/heleket/webhook.
Credit / Debit Card eps BDT, USD Supports Credit / Debit Card payment.
Credit / Debit Card paystation BDT, USD PayStation (Bangladesh): card and local methods via PayStation checkout. USD orders are charged in BDT at the configured USD→BDT rate.
FreeKassa freekassa RUB, USD, EUR, UAH, KZT Two-step flow: createorder without freekassaSystemId returns selectUrl; payer picks method on gateway page (FX quote if needed), then POST /api/freekassa/confirm. List IDs: /api/freekassa/currencies. Notify: /api/gatewaynotification/freekassa/notify (respond YES).
NOWPayments (Crypto) nowpayments USD, EUR, GBP, BRL, NZD Two-step flow: createorder returns selectUrl; payer chooses crypto on gateway page (min-amount check via NOWPayments API), then confirm creates invoice with pay_currency. IPN: POST /api/gatewaynotification/nowpayments/ipn with x-nowpayments-sig verification.
Balance balance CNY, USD Pay from merchant account balance. Instant settlement; no redirect or QR code. Response includes paidWithBalance: true and status=2 (paid).
Payer choice (multi-gateway) select CNY, USD, BDT, EUR, GBP, BRL, NZD Deferred flow: createorder with paymentMethod=select returns selectUrl and nextAction=payment_method_select. Optional lang (default en) sets the payer selection page locale and URL prefix (e.g. /zh/payment/{orderId}?step=select). Payer sees order amount and each method's min/max limits, then POST ?step=confirm with paymentMethod. USD orders also offer balance: payer must log in at /merchant/login; funds are deducted from the payer's platform balance and credited to the merchant. Optional allowedPaymentMethods restricts the list. FreeKassa / NOWPayments still use their secondary selection pages after confirm.
Currency and Payment Method Compatibility:
  • CNY (Chinese Yuan): Supports alipay, wxpay, and balance
  • USD (US Dollar): Supports alipay, wxpay, eps, paystation, freekassa, heleket, nowpayments, and balance
  • BDT (Bangladesh Taka): Supports eps and paystation
  • RUB / UAH / KZT: Supports freekassa only
  • EUR: Supports freekassa and nowpayments
  • GBP / BRL / NZD: Supports nowpayments only

Error Codes

Common error codes and their meanings:

Code Description
400 Bad Request - Invalid parameters or business logic error
401 Unauthorized - Invalid appid or apikey
403 Forbidden — clientip does not match the request IP, or the merchant account is disabled
429 Too Many Requests - Rate limit exceeded
500 Internal Server Error - Server-side error