One integration

Unified API

Base URLhttps://api.4reply.com/v1

One base URL for every 4Reply platform: https://api.4reply.com.

  • Unified API (/v1/..., this section): Free Fire top-ups, Razer Gold PINs and every ShamCash service are listed, bought and followed the same way, with the same JSON.
  • Native APIs (/freefire/..., /razer/..., /shamcash/..., the next sections): each platform's own API, unchanged. If you already integrated a platform, only the host changes.

One key for every platform: sign in at developers.4reply.com with your 4reply account to get your unified API key (4r_...). It works on every platform linked to your 4reply account, here and on the platforms directly, sent the way each platform expects (see Authentication). A platform account that is not linked to 4reply keeps using its own key.

Conventions: JSON bodies (Content-Type: application/json on POST), money amounts as decimal strings ("1.12", "19217.61"), times in ISO 8601 UTC (2026-10-16T12:00:00Z).

Getting started

  1. Pick a service type: GET /v1/services → products (buy) or payments (ShamCash payment check).
  2. Pick a project: GET /v1/projects?service=products → freefire, razer, shamcash.
  3. List its products, with your own price: GET /v1/projects/{project}/products, with that platform's key.
  4. Buy: POST /v1/projects/{project}/orders with your own order_id; the body is the same for every project.
  5. Follow the order: GET /v1/projects/{project}/orders/{order_id}, or receive a webhook when it is final.

Products whose flow is inquiry_then_pay (ShamCash bills) take one more step before buying: POST /v1/projects/shamcash/inquiries returns the amount due and an inquiry_id that the order then sends.

cURL
# products, with your Razer key
curl https://api.4reply.com/v1/projects/razer/products -H "X-API-Key: YOUR_RAZER_KEY"

# buy (your own order_id, UUID recommended)
curl -X POST https://api.4reply.com/v1/projects/razer/orders -H "X-API-Key: YOUR_RAZER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"order_id": "7d1c2a3e-4b5f-4a6b-9c8d-0e1f2a3b4c5d", "product_id": "freefire-pins:11572", "quantity": 1}'

# follow it
curl https://api.4reply.com/v1/projects/razer/orders/7d1c2a3e-4b5f-4a6b-9c8d-0e1f2a3b4c5d -H "X-API-Key: YOUR_RAZER_KEY"

Authentication

Every endpoint under /v1/projects/{project}/... takes your unified key (4r_..., from developers.4reply.com) or, for an account not linked to 4reply, that platform's own API key, in the header the platform expects:

Project Header
freefire Authorization: Bearer <key> or X-API-Key: <key> (unified 4r_..., or the reseller keyId.secret)
razer X-API-Key: <key> (unified 4r_..., or the Razer key)
shamcash X-API-Key: <key> (unified 4r_..., or sham_...)
  • Linking a platform account to 4reply retires that platform's old keys at once: use the unified key from then on. IP allowlists, webhooks and API access are set per platform on developers.4reply.com.

  • /v1/services, /v1/projects, /v1/status and /health need no key.

  • The platform checks the key on every call; its own answer is passed on (401 PLATFORM_KEY_REJECTED, 403 PLATFORM_FORBIDDEN with the platform's message, e.g. an IP not in your allowlist).
  • Your server's IP is forwarded to the platform (X-Forwarded-For), so your platform IP allowlists keep working.
  • 4Reply never stores your key. The only exception: an order with a webhook_url keeps it encrypted until its webhook is delivered (the webhook carries it, see Webhooks), then deletes it. Orders are filed under a fingerprint of the key (HMAC-SHA256), so only the same key can read them back.

Services

cURL
curl https://api.4reply.com/v1/services
JSON
{"data": [
  {"id": "products", "name": "Products", "name_ar": "خدمات المنتجات",
   "description": "Buy a product with the unified API: Free Fire top-ups, Razer Gold PINs and every ShamCash service (transfers, cash-in, mobile top-ups, MTN bundles, bills).",
   "projects": ["freefire", "razer", "shamcash"],
   "endpoints": [{"method": "GET", "path": "/v1/projects/{project}/products", "summary": "Products, with your price"},
                 {"method": "POST", "path": "/v1/projects/{project}/orders", "summary": "Buy"},
                 {"method": "GET", "path": "/v1/projects/{project}/orders/{order_id}", "summary": "Order status"}]},
  {"id": "payments", "name": "Payments", "name_ar": "خدمات المدفوعات",
   "description": "ShamCash payment-check API (API فحص الحوالات التلقائي): confirm the transfers you receive with your ShamCash transaction history and search. Called with your ShamCash key, exactly as on shamcash.4reply.com.",
   "projects": ["shamcash"],
   "endpoints": [{"method": "GET", "path": "/shamcash/account/history", "summary": "Last 10 operations of the account"},
                 {"method": "POST", "path": "/shamcash/account/history/search", "summary": "Find one operation by its tranId"},
                 {"method": "POST", "path": "/shamcash/account/history/filter", "summary": "Filter operations by tranId, peer account, currency or date range"}]}
]}
Service Arabic Projects What it is
products خدمات المنتجات freefire, razer, shamcash Everything you buy: Free Fire diamonds, Razer PINs and direct top-ups, and every ShamCash service: transfers, Syriatel / MTN Cash cash-in, top-ups, MTN bundles, postpaid and utility bills.
payments خدمات المدفوعات shamcash ShamCash's payment-check API ("API فحص الحوالات التلقائي"): read your ShamCash history and search an operation to confirm a transfer you received. It is ShamCash's own API, used through /shamcash/account/history* (see the ShamCash API section, "Operation queries").

Projects

GET /v1/projects (optionally ?service=products|payments) and GET /v1/projects/{project}:

JSON
{"id": "razer", "name": "Razer Gold", "description": "Razer Gold PINs and direct top-ups bought from your own Razer accounts.",
 "services": ["products"], "auth_header": "X-API-Key: <key>", "native_base_url": "https://api.4reply.com/razer",
 "website": "https://rz.4reply.com"}
Project Platform Native base URL
freefire Free Fire top-up gateway (ff.4reply.com) https://api.4reply.com/freefire
razer Razer Gold PIN store (rz.4reply.com) https://api.4reply.com/razer
shamcash ShamCash payments (shamcash.4reply.com) https://api.4reply.com/shamcash

GET/v1/projects/{project}/balance

Your balance on that platform.

JSON
{"project": "shamcash", "balances": [{"currency": "SYP", "amount": "150000", "label": "balance"},
                                      {"currency": "USD", "amount": "12.5", "label": "balance"}]}

Free Fire: wallet (USD). Razer: site_wallet (USD, the site balance that pays commissions; the Razer Gold itself is on your Razer accounts). ShamCash: one entry per currency.

Products

GET/v1/projects/{project}/products

Every product of the project in one shape, with your own price. Filters: ?category=, ?available=true, ?service=products|payments. Razer only: ?account_email= picks which of your Razer accounts' catalog (region) and prices you see (default: your first active account).

Catalogs are cached about 60 seconds (Razer: about 10 minutes, since each Razer category is a live call to Razer; use ?category= to load just one).

GET /v1/projects/{project}/products/{product_id} returns one product:

JSON
{
  "id": "freefire-pins:11572",
  "project": "razer",
  "service": "products",
  "category": "freefire-pins",
  "name": "FreeFire USD 1 (100 Diamonds)",
  "name_ar": null,
  "description": null,
  "icon": null,
  "price": {"amount": "1.12", "currency": "USD"},
  "currency": "USD",
  "pricing": "fixed",
  "min_amount": null,
  "max_amount": null,
  "step": null,
  "cost_formula": null,
  "fields": [
    {"name": "account_email", "label": "Razer account", "label_ar": null, "type": "select", "required": false,
     "min": null, "max": null, "options": [{"value": "me@shop.com", "label": "me@shop.com"}], "pattern": null,
     "description": "Which of your Razer accounts pays (its Razer Gold balance). Default: me@shop.com."}
  ],
  "flow": "direct",
  "max_quantity": 20,
  "available": true
}
Field Meaning
id Product id inside its project; send it as product_id.
service products (every product of every project).
category The platform's own category (freefire-pins, mtn-bundles, transfer...).
name, name_ar English name; Arabic name when the platform has one.
price Your own unit price (your platform price rules applied: Free Fire customer price, Razer unitPrice + your commission, ShamCash charged price with tax), or null when there is no fixed price (custom amounts, bills) or it cannot be determined. A provider / base price is never shown instead.
currency Currency of the price, or of the amount you send.
pricing fixed (price × quantity), custom_amount (you send amount), bill_amount (the inquiry decides it).
min_amount, max_amount, step Limits of amount for custom_amount products (amount must be a multiple of step).
cost_formula When the platform charges more than amount, e.g. "ceil(amount * 1.04)" (Syriatel top-up).
fields What to send in the order's fields. min/max are lengths for text and values for numbers; pattern is a regular expression; options lists the allowed values.
flow direct, or inquiry_then_pay (inquiry first).
max_quantity Highest quantity per order (1 for custom amounts and bills).
available false when out of stock or disabled.

Buying

POST/v1/projects/{project}/orders

The same body for every project:

Field Type Meaning
order_id string Required. Your own unique id for the order (1-100 characters: letters, digits, . _ : -). A UUID is recommended, and required for Free Fire (same rule as Free Fire's order_id). UUIDs are stored in lower case.
product_id string From the catalog.
quantity integer Default 1, at most the product's max_quantity.
fields object What the product's fields declare (player id, phone number, ShamCash address, Razer account...).
amount string / number / null Only for custom_amount products (optional for bills, where it must equal the bill).
inquiry_id string For inquiry_then_pay products.
bill_index integer Which bill of the inquiry to pay (default 0).
webhook_url string Optional https:// URL that receives the final result (see Webhooks).
JSON
{"order_id": "7d1c2a3e-4b5f-4a6b-9c8d-0e1f2a3b4c5d", "product_id": "freefire-pins:11572", "quantity": 1,
 "fields": {}, "amount": null, "webhook_url": "https://shop.example.com/hooks/4reply"}

Response 201 (a new order): the order object (below).

Your order_id is never executed twice, on any platform:

  • Sending the same order_id again with the same body returns the existing order (200) without buying again.
  • The same order_id with a different body is refused: 409 DUPLICATE_ORDER.
  • Free Fire: it is sent as Free Fire's own order_id (its native idempotency). Razer: it is sent as Razer's own order_id on every purchase, and Razer's purchase log is looked up by it. ShamCash has no order id of its own: 4Reply records your order_id with ShamCash's transactionId.

A purchase can take 1-2 minutes on the platform. The request waits for the platform's answer (up to about 90 seconds) and returns the order; an order that takes longer (a slow checkout, several Razer PINs) is returned as processing or pending and goes on in the background: read it again by its order_id, or use a webhook_url. A platform's refusal (insufficient balance, wrong phone number...) is a recorded order with status: "failed" and an error; use a new order_id to try again.

Inquiries

POST /v1/projects/{project}/inquiries with product_id, fields (and quantity). Required before ordering an inquiry_then_pay product (ShamCash bills); for Free Fire it is an optional player check.

JSON
{"product_id": "electricity", "fields": {"gov": "Homs", "subscription": "349034", "billingno": "248667"}}

Response 201:

JSON
{
  "inquiry_id": "inq_36e3f40184c90f0ec38756d4",
  "project": "shamcash",
  "product_id": "electricity",
  "quantity": 1,
  "fields": {"gov": "Homs", "subscription": "349034", "billingno": "248667"},
  "amount_due": "19217.61",
  "currency": "SYP",
  "bills": [{"index": 0, "amount": "19217.61", "currency": "SYP",
             "details": {"billing_no": "03_248667_349034", "bill_no": "68839134", "amount": "19217.61",
                         "currency": "SYP", "note": "اسم المشترك:جورج,الدورة:202506"}}],
  "details": {},
  "created_at": "2026-10-16T12:00:00Z",
  "expires_at": "2026-10-16T12:15:00Z",
  "order_id": null
}

An inquiry pays one order, within 15 minutes. With several bills (landline), pick one with bill_index in the order. GET /v1/projects/{project}/inquiries/{inquiry_id} reads it again.

Order status

GET/v1/projects/{project}/orders/{order_id}

The order, by your order_id, re-read from the platform when it is not final (at most every 20 seconds). GET /v1/projects/{project}/orders lists your orders (newest first; status, limit up to 200, offset).

JSON
{
  "order_id": "7d1c2a3e-4b5f-4a6b-9c8d-0e1f2a3b4c5d",
  "project": "razer",
  "product_id": "freefire-pins:11572",
  "status": "completed",
  "status_detail": null,
  "quantity": 1,
  "amount": "1.12",
  "currency": "USD",
  "fields": {"account_email": "me@shop.com"},
  "result": {
    "account_email": "me@shop.com",
    "delivered": 1,
    "failed": 0,
    "pins": [{"pin": "X426L82QRKRTCJ79", "serial": "69b14a1365257", "expiry": "9999-12-31",
              "transaction_number": "122K9T9VWE5S6D8373764"}],
    "units": [{"index": 1, "status": "completed", "transaction_number": "122K9T9VWE5S6D8373764", "error": null,
               "product_name": "FreeFire USD 1 (100 Diamonds)", "razer_status": "SUCCESS", "razer_amount": "1.07",
               "currency": "USD"}]
  },
  "error": null,
  "inquiry_id": null,
  "webhook_url": "https://shop.example.com/hooks/4reply",
  "platform_refs": {"order_id": "7d1c2a3e-4b5f-4a6b-9c8d-0e1f2a3b4c5d",
                    "transaction_numbers": ["122K9T9VWE5S6D8373764"]},
  "created_at": "2026-10-16T12:00:00Z",
  "updated_at": "2026-10-16T12:00:41Z"
}

platform_refs are the platform's own references, unchanged, to find the order on the platform itself:

Project platform_refs
freefire order_id: Free Fire's order id (your UUID)
razer order_id: the order_id sent to Razer (yours); transaction_numbers: Razer's transaction numbers
shamcash transactionId: ShamCash's operation number (ShamCash returns none for transfers)

Statuses

status Meaning Final
pending Accepted, not started yet, or the platform's answer was lost (status_detail: "unconfirmed"). no
processing Being delivered. no
completed Delivered. status_detail: "partial" when only part of the quantity was delivered (see result). yes
failed Not delivered; nothing (more) is charged. error says why (error.rejected_input: true when your input was wrong). yes
refunded Charged, then refunded by the platform. yes
Platform Mapping
Free Fire pending → pending; processing, retrying → processing; completed → completed; partial → completed + partial; failed → failed; refunded → refunded
Razer per PIN: SUCCESS → delivered; OUT_OF_STOCK, FAILED... → failed; details still loading → processing. The order is completed when every unit is delivered, failed when none is, completed + partial otherwise.
ShamCash succeeded: true → completed; succeeded: false → failed

A purchase is never sent twice. If the platform does not answer (timeout, 5xx), the order is kept pending with status_detail: "unconfirmed". Keep polling: Free Fire orders resolve from Free Fire's own order, Razer orders from Razer's purchase log for your order_id. ShamCash has no order-status endpoint, so an unconfirmed ShamCash order stays pending: check it in your ShamCash history (/shamcash/account/history/search) before paying again with a new order_id.

Razer orders of several units are bought one PIN at a time (Razer's order_id purchases are per unit), in order, and stop at the first unit that is not delivered; the remaining units are reported failed with NOT_ATTEMPTED and are never sent.

result per project

Project result
freefire player_id, player_name, product_name, delivered (units), units[] (id, status, amount, player_name, completed_at), completed_at
razer account_email, delivered, failed, pins[] (pin, serial, expiry, transaction_number), units[] (index, status, transaction_number, product_name, razer_status, razer_amount, currency, error)
shamcash transaction_id, message, bill (the paid bill, for bill payments)

amount is the order total: price × quantity for fixed products (only units not failed, once known), the amount you sent for custom amounts, the bill amount for bills.

Webhooks

Add webhook_url (https only) to an order and 4Reply POSTs the result once the order is final. The payload is modelled on Free Fire's reseller webhook, so a Free Fire integration recognises it:

HTTP
POST https://shop.example.com/hooks/4reply
Content-Type: application/json
api-token: YOUR_RAZER_KEY
X-4Reply-Event: order.completed
User-Agent: 4reply-webhook/1.0
JSON
{
  "orderId": "7d1c2a3e-4b5f-4a6b-9c8d-0e1f2a3b4c5d",
  "project": "razer",
  "status": 1,
  "message": "order completed",
  "order": {"order_id": "7d1c2a3e-4b5f-4a6b-9c8d-0e1f2a3b4c5d", "project": "razer", "status": "completed", "...": "the order object"}
}
status Event When
1 order.completed Completed (everything delivered).
2 order.failed Rejected because of the input: invalid player id, unknown Razer account, wrong phone number or ShamCash account...
0 order.failed Any other result: partial delivery, refund, other failure (message says why).
  • api-token is the same platform key the order was placed with, exactly as Free Fire sends it: Free Fire <keyId>.<secret> (without Bearer), Razer and ShamCash the key itself. Compare it in constant time.
  • Answer with any 2xx quickly. Network errors, 429 and 5xx are retried after 30 s, 2 min, 10 min, 30 min and 2 h; other answers stop the deliveries. Key your handler by orderId: a retry may deliver twice.
  • Orders that are not final yet are followed in the background (reads only) for up to 24 hours. Your key is kept encrypted only until the webhook is delivered (or given up), then deleted.
  • GET /v1/projects/{project}/orders/{order_id} stays the source of truth; GET /v1/projects/{project}/orders/{order_id}/webhooks lists the delivery attempts.
  • Free Fire's own webhook (set in the Free Fire dashboard) keeps working unchanged and independently: it is sent by Free Fire for every Free Fire order, with or without a unified webhook_url.

Errors

Every error of the unified API has the same envelope:

JSON
{"error": {"code": "MISSING_API_KEY", "message": "Send your razer API key: X-API-Key: <key>", "project": "razer", "upstream_status": null}}

project and upstream_status (the platform's HTTP status) are set when a platform is involved; some errors add details. Branch on code, not on message. (The native sections return each platform's own errors.)

HTTP code Meaning
400 UPSTREAM_REJECTED The platform refused the request (its message is passed on).
400 INQUIRY_FAILED The bill / player look-up failed (e.g. "No bills found").
400 INQUIRY_NOT_SUPPORTED The product needs no inquiry.
401 MISSING_API_KEY No platform key sent (the message names the header).
401 PLATFORM_KEY_REJECTED The platform does not accept the key.
402 UPSTREAM_SUBSCRIPTION_REQUIRED The platform requires an active API subscription.
403 PLATFORM_FORBIDDEN The platform refused the call (IP allowlist, no active session...).
404 PROJECT_NOT_FOUND, SERVICE_NOT_FOUND, PRODUCT_NOT_FOUND, ORDER_NOT_FOUND, INQUIRY_NOT_FOUND, NOT_FOUND Unknown id or path.
404 NO_BILLS The inquiry found nothing to pay.
409 DUPLICATE_ORDER This order_id exists with different parameters (details.order_id).
409 PRODUCT_UNAVAILABLE Out of stock / disabled.
409 INQUIRY_USED The inquiry already paid an order.
410 INQUIRY_EXPIRED Make a new inquiry.
422 VALIDATION_ERROR Malformed body or query.
422 INVALID_UUID_FORMAT Free Fire order_id is not a UUID.
422 INVALID_FIELD A product field is missing or wrong (details.field).
422 INVALID_AMOUNT, INVALID_QUANTITY, INVALID_BILL amount, quantity or bill_index outside the product's limits.
422 INQUIRY_REQUIRED, INQUIRY_MISMATCH Send a matching inquiry_id.
422 INVALID_WEBHOOK_URL webhook_url must be a public https:// URL.
429 UPSTREAM_RATE_LIMITED The platform's rate limit.
500 INTERNAL_ERROR Gateway bug.
502 UPSTREAM_ERROR The platform answered with an error.
503 UPSTREAM_UNAVAILABLE The platform cannot be reached (nothing was sent).
504 UPSTREAM_TIMEOUT, UPSTREAM_NO_ANSWER No answer in time (UPSTREAM_NO_ANSWER: a native write whose outcome is unknown).

A failed order carries the same kind of object in its error, e.g. {"code": "INSUFFICIENT_BALANCE", "message": "Insufficient wallet balance", "upstream_status": 400} (Free Fire codes such as PLAYER_NOT_FOUND or PRICE_INCREASED are passed on), PAYMENT_REJECTED (ShamCash), NOT_ATTEMPTED (a Razer unit that was not sent), UPSTREAM_UNAVAILABLE (the request could not be sent; nothing was charged) or ORDER_NOT_REGISTERED (Free Fire never received the order).

Examples

The same request, three platforms:

cURL
# Free Fire top-up
curl -X POST https://api.4reply.com/v1/projects/freefire/orders \
  -H "Authorization: Bearer KEY_ID.SECRET" -H "Content-Type: application/json" \
  -d '{"order_id": "01912345-6789-7abc-8def-0123456789ab", "product_id": "28", "quantity": 1, "fields": {"player_id": "14679257282"}}'

# Razer Gold PIN
curl -X POST https://api.4reply.com/v1/projects/razer/orders \
  -H "X-API-Key: YOUR_RAZER_KEY" -H "Content-Type: application/json" \
  -d '{"order_id": "7d1c2a3e-4b5f-4a6b-9c8d-0e1f2a3b4c5d", "product_id": "freefire-pins:11572", "quantity": 1, "fields": {}}'

# ShamCash transfer
curl -X POST https://api.4reply.com/v1/projects/shamcash/orders \
  -H "X-API-Key: sham_..." -H "Content-Type: application/json" \
  -d '{"order_id": "2b9f6c1e-0d3a-4e5b-8c7d-6f5e4d3c2b1a", "product_id": "transfer-usd", "quantity": 1, "fields": {"accountAddress": "f9a5242a7e75c8e54d3afbf3183fa228"}, "amount": "25"}'

# ShamCash electricity bill: inquiry, then the order
curl -X POST https://api.4reply.com/v1/projects/shamcash/inquiries \
  -H "X-API-Key: sham_..." -H "Content-Type: application/json" \
  -d '{"product_id": "electricity", "fields": {"gov": "Homs", "subscription": "349034", "billingno": "248667"}}'
curl -X POST https://api.4reply.com/v1/projects/shamcash/orders \
  -H "X-API-Key: sham_..." -H "Content-Type: application/json" \
  -d '{"order_id": "5c4b3a29-1807-4f6e-9d5c-4b3a29180765", "product_id": "electricity", "inquiry_id": "inq_36e3f40184c90f0ec38756d4"}'

Free Fire order, completed (GET /v1/projects/freefire/orders/01912345-6789-7abc-8def-0123456789ab):

JSON
{"order_id": "01912345-6789-7abc-8def-0123456789ab", "project": "freefire", "product_id": "28",
 "status": "completed", "status_detail": null, "quantity": 1, "amount": "1.0265", "currency": "USD",
 "fields": {"player_id": "14679257282"},
 "result": {"player_id": "14679257282", "player_name": "ProGamer99", "product_name": "100 + 10 Diamonds",
            "delivered": 1, "units": [{"id": 1, "status": "completed", "amount": "1.0265", "player_name": "ProGamer99",
                                       "completed_at": "2026-10-16T12:00:04.000Z"}],
            "completed_at": "2026-10-16T12:00:04.000Z"},
 "error": null, "inquiry_id": null, "webhook_url": null,
 "platform_refs": {"order_id": "01912345-6789-7abc-8def-0123456789ab"},
 "created_at": "2026-10-16T12:00:00Z", "updated_at": "2026-10-16T12:00:21Z"}

ShamCash top-up, completed:

JSON
{"order_id": "2b9f6c1e-0d3a-4e5b-8c7d-6f5e4d3c2b1a", "project": "shamcash", "product_id": "syriatel-units",
 "status": "completed", "status_detail": null, "quantity": 1, "amount": "500", "currency": "SYP",
 "fields": {"phoneNumber": "0933333333"}, "result": {"transaction_id": "36479254", "message": "Successfully"},
 "error": null, "inquiry_id": null, "webhook_url": null, "platform_refs": {"transactionId": "36479254"},
 "created_at": "2026-10-16T12:00:00Z", "updated_at": "2026-10-16T12:00:02Z"}

Native APIs

Each platform's own customer API is also reachable at https://api.4reply.com, byte for byte: same paths, same headers, same bodies and answers. Every platform has the same base URL shape, https://api.4reply.com/<project>, which stands for that platform's own API base URL:

Platform's own URL Through 4Reply
https://ff.4reply.com/api/endpoints/v1/... https://api.4reply.com/freefire/...
https://rz.4reply.com/api/... https://api.4reply.com/razer/...
https://shamcash.4reply.com/api/... https://api.4reply.com/shamcash/...
  • Only the customer API endpoints documented in the next sections are reachable; anything else answers 404.
  • Your server's IP is forwarded (X-Forwarded-For), so the platform's IP allowlist keeps working.
  • A request that is not a GET is sent once and never repeated; if no complete answer comes back the gateway answers 504 UPSTREAM_NO_ANSWER (the outcome is unknown: check before sending it again).
  • The platforms' own base URLs keep working too.

GET/v1/status

Pings each platform (no key needed).

JSON
{"ok": true, "projects": [{"project": "freefire", "ok": true, "upstream_status": 200, "latency_ms": 12},
                          {"project": "razer", "ok": true, "upstream_status": 200, "latency_ms": 9},
                          {"project": "shamcash", "ok": true, "upstream_status": 200, "latency_ms": 11}]}

GET /health answers {"ok": true, "version": "2.0.0"} without calling any platform.

Platform API

Free Fire API

Base URLhttps://api.4reply.com/freefire

A single REST interface to top up Free Fire: fetch catalog, validate player, create orders, and receive results via webhook or polling.

This is the direct server-to-server (H2H) top-up API. It is a standard JSON interface over HTTPS with Bearer authentication, UUID idempotency keys, published rate limits, and machine-readable error codes—enabling any store, checkout system, or bot to sell Free Fire diamonds programmatically without third-party SDKs.

This section reproduces the Free Fire reseller API documentation of ff.4reply.com. Through 4Reply the requests and answers are exactly the same; only the host changes. The platform's own base URL keeps working.

Base URL

Base URL
Through 4Reply https://api.4reply.com/freefire
Platform's own (still works) https://ff.4reply.com/api/endpoints/v1

Every path documented here is relative to this base URL. Responses are standard JSON and always include a boolean success field, so a single check in your client separates success from all other outcomes.

Your first call, before writing code

Every endpoint is a standard HTTPS request with a single header. No SDK to install, no client library to import, no build steps. Paste the snippet below into your terminal to get a live catalog response.

cURL
curl -s "https://api.4reply.com/freefire/catalog/categories?bigCategoryId=1" \
  -H "Authorization: Bearer YOUR_KEY_ID.YOUR_KEY_SECRET"

Response - 200 OK:

JSON
{
  "success": true,
  "categories": [
    {
      "id": 12,
      "name": "Free Fire",
      "description": "Garena Free Fire diamonds",
      "big_category_id": 1,
      "big_category_name": "Mobile Games"
    }
  ]
}

Conventions & Error Envelope

  • HTTPS only: Non-secure connections are strictly rejected.
  • JSON format: All request payloads and response bodies use standard JSON.
  • Decimal string amounts: Currency amounts are always 6-decimal strings (e.g. "1.070000") to avoid floating-point inaccuracies.
  • UTC timestamps: All timestamps follow ISO 8601 in UTC (YYYY-MM-DDTHH:MM:SSZ).
  • Pagination: Listing endpoints return a pagination object with page, limit, total, and total_pages.
  • Idempotency: Order creation is safe against duplicates using the client-generated UUID in order_id.

Error Envelope

Failed responses maintain the same shape across all status codes. Always branch on error.code which is part of the API contract; never branch on error.message which is human-readable and subject to change.

Standard Error Response:

JSON
{
  "success": false,
  "error": {
    "code": "PRICE_INCREASED",
    "message": "Price has increased beyond expected",
    "details": {
      "expected_unit_price": "0.950000",
      "current_unit_price": "0.980000"
    }
  }
}

Complete API Surface at a Glance

Eleven endpoints covering the entire integration lifecycle: catalog discovery, real-time pricing, player validation, order creation, and post-order reconciliation.

Method Path Description Rate Limit
GET /account Account details and wallet balance 60 req / 60s
GET /catalog/big-categories List big game categories 80 req / 60s
GET /catalog/categories List game categories (Free Fire) 80 req / 60s
GET /catalog/subcategories Free Fire diamond packages 80 req / 60s
GET /catalog/subcategory/:itemId/price Get real-time unit price 80 req / 60s
GET /catalog/category/:categoryId/requirements Required game fields (player_id) 80 req / 60s
POST /player/validate Validate player ID and in-game nickname Dedicated limit
POST /orders/create Create direct top-up order with UUID 120 req / 60s
GET /orders/:orderId Query single order status by UUID 3 req / 60s
POST /orders/batch Batch order status query (up to 50) 2 req / 60s
GET /orders Paginated order history 2 req / 60s

Authentication & Access Control

Authentication requires a single HTTP header. Every request must include an Authorization header containing a Bearer credential composed of a Key ID and Secret separated by a dot:

HTTP
Authorization: Bearer <keyId>.<secret>
  • Key ID: Identifies your reseller account in the system.
  • Secret: Proves account ownership and is verified on the server using constant-time HMAC comparison.
  • No sessions or refresh tokens: No OAuth redirects, session cookies, or expiring tokens to schedule.
  • IP Allowlist: Pin API access to your server IPs. Requests from unauthorized IPs are rejected immediately with IP_NOT_ALLOWED (HTTP 403) before processing. Through 4Reply your server's IP is forwarded, so the allowlist keeps working.
  • Account status: Disabled accounts receive ACCOUNT_DISABLED and frozen accounts receive ACCOUNT_FROZEN (HTTP 403).
  • Health check: GET /account verifies key validity and available wallet balance before submitting orders.

To generate and rotate API keys and configure allowed IP addresses, go to API Settings in your Profile on ff.4reply.com.

End-to-End Integration Flow

A typical integration follows four core steps to ensure reliable delivery and prevent double-charging:

  1. Read Catalog: Browse categories and diamond packages to obtain current item IDs and real-time prices.
  2. Validate Player: Resolve the player ID to an in-game nickname and region before any funds move.
  3. Create Order: Generate a UUID and pass it as order_id for idempotency and price protection.
  4. Confirm Delivery: Receive the webhook callback or poll order status until completion.

cURL - Complete Flow:

cURL
export S2T_KEY="YOUR_KEY_ID.YOUR_KEY_SECRET"
export S2T_BASE="https://api.4reply.com/freefire"

# 1. Fetch Free Fire catalog (Category 12)
curl -s "$S2T_BASE/catalog/subcategories?categoryId=12" \
  -H "Authorization: Bearer $S2T_KEY"

# 2. Get real-time price that will be charged
curl -s "$S2T_BASE/catalog/subcategory/100/price" \
  -H "Authorization: Bearer $S2T_KEY"

# 3. Validate player ID and nickname before charging balance
curl -s -X POST "$S2T_BASE/player/validate" \
  -H "Authorization: Bearer $S2T_KEY" \
  -H "Content-Type: application/json" \
  -d '{"sub_category_id": 100, "player_id": "14679257282"}'

# 4. Create order with UUID idempotency key & price protection
curl -s -X POST "$S2T_BASE/orders/create" \
  -H "Authorization: Bearer $S2T_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "order_id": "01912345-6789-7abc-8def-0123456789ab",
    "sub_category_id": 100,
    "quantity": 1,
    "requirements": { "player_id": "14679257282" },
    "expected_unit_price": "1.070000"
  }'

# 5. Poll order status until it leaves pending
curl -s "$S2T_BASE/orders/01912345-6789-7abc-8def-0123456789ab" \
  -H "Authorization: Bearer $S2T_KEY"

Node.js (18+) - Complete Flow:

JavaScript
// Node 18+ — global fetch and global crypto
const BASE = 'https://api.4reply.com/freefire';
const KEY = process.env.S2T_KEY || 'YOUR_KEY_ID.YOUR_KEY_SECRET';

async function call(path, init = {}) {
  const res = await fetch(BASE + path, {
    ...init,
    headers: {
      Authorization: `Bearer ${KEY}`,
      'Content-Type': 'application/json',
      ...(init.headers || {}),
    },
  });

  if (res.status === 429) {
    const wait = Number(res.headers.get('Retry-After') || 5);
    await new Promise((r) => setTimeout(r, wait * 1000));
    return call(path, init);
  }

  const body = await res.json();
  if (!res.ok || body.success === false) {
    throw Object.assign(new Error(body?.error?.code || 'HTTP_' + res.status), {
      code: body?.error?.code,
      status: res.status,
    });
  }
  return body;
}

async function topUpFreeFire({ itemId = 100, playerId = '14679257282' }) {
  // 1 + 2. Catalog & real-time price
  const { price } = await call(`/catalog/subcategory/${itemId}/price`);

  // 3. Validate player before charging balance
  const { player } = await call('/player/validate', {
    method: 'POST',
    body: JSON.stringify({ sub_category_id: itemId, player_id: playerId }),
  });

  // 4. Create order with pre-generated UUID to prevent double-charging
  const orderId = crypto.randomUUID();
  const { order } = await call('/orders/create', {
    method: 'POST',
    body: JSON.stringify({
      order_id: orderId,
      sub_category_id: itemId,
      quantity: 1,
      requirements: { player_id: playerId },
      expected_unit_price: price.unit_price,
    }),
  });

  // 5. Confirm delivery
  let status = order.status;
  while (status === 'pending') {
    await new Promise((r) => setTimeout(r, 10000));
    status = (await call(`/orders/${orderId}`)).order.status;
  }

  return { orderId, status, playerName: player.player_name };
}

PHP 8 - Complete Flow:

PHP
<?php
const S2T_BASE = 'https://api.4reply.com/freefire';

function s2t(string $path, ?array $body = null): array {
    $ch = curl_init(S2T_BASE . $path);
    $headers = [
        'Authorization: Bearer ' . getenv('S2T_KEY'),
        'Content-Type: application/json',
    ];
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER     => $headers,
        CURLOPT_TIMEOUT        => 30,
    ]);
    if ($body !== null) {
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
    }
    $raw    = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    $data = json_decode($raw, true) ?: [];
    if ($status >= 400 || ($data['success'] ?? false) === false) {
        throw new RuntimeException($data['error']['code'] ?? 'HTTP_' . $status);
    }
    return $data;
}

// 1 + 2. Get real-time price
$price = s2t('/catalog/subcategory/100/price');

// 3. Validate player
$player = s2t('/player/validate', [
    'sub_category_id' => 100,
    'player_id'       => '14679257282',
]);

// 4. Create order with UUID idempotency key
$orderId = vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex(random_bytes(16)), 4));
$order = s2t('/orders/create', [
    'order_id'            => $orderId,
    'sub_category_id'     => 100,
    'quantity'            => 1,
    'requirements'        => ['player_id' => '14679257282'],
    'expected_unit_price' => $price['price']['unit_price'],
]);

// 5. Poll status until complete
do {
    sleep(10);
    $latest = s2t('/orders/' . $orderId);
} while ($latest['order']['status'] === 'pending');

echo $latest['order']['status'];

Detailed Endpoints Reference

Comprehensive documentation of all parameters, responses, and examples for all 11 endpoints:

GET/account

Rate limit: 60 req / 60s per user.

Used to verify API key validity, ensure the account is active, and read available wallet balance.

Response Fields (account):

Field Type Description
id number Numeric account identifier
email string Registered email address
username string Account username
client_type string Client type ("reseller")
wallet string (decimal) Available wallet balance in USD (6 decimal places)
enabled boolean Whether the account is enabled
verified boolean Whether the account is verified
created_at string (ISO 8601) Account creation timestamp

Relevant errors: MISSING_API_KEY, INVALID_API_KEY, ACCOUNT_DISABLED, ACCOUNT_FROZEN, IP_NOT_ALLOWED, RATE_LIMIT_EXCEEDED.

cURL
curl -s "https://api.4reply.com/freefire/account" \
  -H "Authorization: Bearer YOUR_KEY_ID.YOUR_KEY_SECRET"

Response Example - 200 OK:

JSON
{
  "success": true,
  "account": {
    "id": 42,
    "email": "partner@example.com",
    "username": "partner_store",
    "client_type": "reseller",
    "wallet": "1250.500000",
    "enabled": true,
    "verified": true,
    "created_at": "2026-01-15T10:30:00Z"
  }
}

GET/catalog/big-categories

Rate limit: 80 req / 60s (shared).

List major game categories.

Query Parameter Type Required Description Example
for_ui boolean no Include image URLs in response true
cURL
curl -s "https://api.4reply.com/freefire/catalog/big-categories?for_ui=true" \
  -H "Authorization: Bearer YOUR_KEY_ID.YOUR_KEY_SECRET"

Response Example - 200 OK:

JSON
{
  "success": true,
  "big_categories": [
    {
      "id": 1,
      "name": "Mobile Games",
      "description": "Popular mobile game top-ups"
    }
  ]
}

GET/catalog/categories

Rate limit: 80 req / 60s (shared).

List available game categories (Free Fire is category ID 12).

Query Parameter Type Required Description Example
bigCategoryId number no Filter by big category ID (1 for mobile games) 1
for_ui boolean no Include image URLs in response true
cURL
curl -s "https://api.4reply.com/freefire/catalog/categories?bigCategoryId=1" \
  -H "Authorization: Bearer YOUR_KEY_ID.YOUR_KEY_SECRET"

Response Example - 200 OK:

JSON
{
  "success": true,
  "categories": [
    {
      "id": 12,
      "name": "Free Fire",
      "description": "Garena Free Fire diamonds",
      "big_category_id": 1,
      "big_category_name": "Mobile Games"
    }
  ]
}

GET/catalog/subcategories

Rate limit: 80 req / 60s (shared).

List Free Fire diamond packages (Subcategories) with their item_id. Prices shown match the actual live catalog.

Query Parameter Type Required Description Example
categoryId number no Filter by category ID (12 for Free Fire) 12
cURL
curl -s "https://api.4reply.com/freefire/catalog/subcategories?categoryId=12" \
  -H "Authorization: Bearer YOUR_KEY_ID.YOUR_KEY_SECRET"

Response Example - 200 OK:

JSON
{
  "success": true,
  "subcategories": [
    {
      "item_id": 100,
      "name": "FF 100 Diamonds",
      "description": "100 Free Fire Diamonds",
      "category_id": 12,
      "category_name": "Free Fire",
      "price": "1.07",
      "fulfillment_type": "api",
      "returns_voucher": false
    },
    {
      "item_id": 210,
      "name": "FF 210 Diamonds",
      "description": "210 Free Fire Diamonds",
      "category_id": 12,
      "category_name": "Free Fire",
      "price": "2.14",
      "fulfillment_type": "api",
      "returns_voucher": false
    },
    {
      "item_id": 530,
      "name": "FF 530 Diamonds",
      "description": "530 Free Fire Diamonds",
      "category_id": 12,
      "category_name": "Free Fire",
      "price": "5.35",
      "fulfillment_type": "api",
      "returns_voucher": false
    },
    {
      "item_id": 1080,
      "name": "FF 1080 Diamonds",
      "description": "1080 Free Fire Diamonds",
      "category_id": 12,
      "category_name": "Free Fire",
      "price": "10.70",
      "fulfillment_type": "api",
      "returns_voucher": false
    },
    {
      "item_id": 2200,
      "name": "FF 2200 Diamonds",
      "description": "2200 Free Fire Diamonds",
      "category_id": 12,
      "category_name": "Free Fire",
      "price": "21.40",
      "fulfillment_type": "api",
      "returns_voucher": false
    }
  ]
}

GET/catalog/subcategory/:itemId/price

Rate limit: 80 req / 60s (shared).

Get the real-time unit price that will be deducted from your wallet. Use unit_price as expected_unit_price when creating orders.

Path Parameter Type Required Description Example
itemId number yes Package item ID (e.g. 100) 100

Relevant errors: ITEM_NOT_FOUND, INVALID_ITEM_ID.

cURL
curl -s "https://api.4reply.com/freefire/catalog/subcategory/100/price" \
  -H "Authorization: Bearer YOUR_KEY_ID.YOUR_KEY_SECRET"

Response Example - 200 OK:

JSON
{
  "success": true,
  "price": {
    "item_id": 100,
    "item_name": "FF 100 Diamonds",
    "unit_price": "1.026500",
    "currency": "USD",
    "original_price": "1.070000",
    "discount_applied": true,
    "discount_percent": "5.00",
    "fee": "0.010000",
    "timestamp": "2026-08-28T12:00:00Z"
  }
}

GET/catalog/category/:categoryId/requirements

Rate limit: 80 req / 60s (shared).

Get the required input fields for this game (player_id for Free Fire).

Path Parameter Type Required Description Example
categoryId number yes Category ID (12 for Free Fire) 12

Relevant errors: INVALID_CATEGORY_ID.

cURL
curl -s "https://api.4reply.com/freefire/catalog/category/12/requirements" \
  -H "Authorization: Bearer YOUR_KEY_ID.YOUR_KEY_SECRET"

Response Example - 200 OK:

JSON
{
  "success": true,
  "requirements": [
    {
      "field_name": "player_id",
      "data_type": "text",
      "placeholder": "Enter Free Fire Player ID"
    }
  ]
}

POST/player/validate

Rate limit: dedicated limit.

Validate the player ID and retrieve their in-game nickname and region to verify before deducting balance.

Body Parameter Type Required Description Example
sub_category_id number yes Package item ID (e.g. 100) 100
player_id string yes In-game player ID 14679257282

Relevant errors: MISSING_REQUIRED_FIELD, INVALID_SUBCATEGORY, PLAYER_NOT_FOUND, PLAYER_VALIDATION_FAILED.

cURL
curl -s -X POST "https://api.4reply.com/freefire/player/validate" \
  -H "Authorization: Bearer YOUR_KEY_ID.YOUR_KEY_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
  "sub_category_id": 100,
  "player_id": "14679257282"
}'

Response Example - 200 OK:

JSON
{
  "success": true,
  "player": {
    "player_id": "14679257282",
    "player_name": "ProGamer99",
    "region": "MENA"
  }
}

POST/orders/create

Rate limit: 120 req / 60s per user.

Create a direct top-up order. The order_id field is your UUID idempotency key. Resending with the same UUID returns the existing record without duplicate charging.

Body Parameter Type Required Description Example
order_id string (UUID) yes Unique order identifier in UUID v1/v4/v7 format 01912345-6789-7abc-8def-0123456789ab
sub_category_id number yes Package item ID (e.g. 100) 100
quantity number yes Number of units (positive integer >= 1) 1
requirements object yes Fulfillment data (must contain player_id) {"player_id": "14679257282"}
expected_unit_price string no Price protection: rejected with PRICE_INCREASED if price rises 1.070000

Relevant errors: INVALID_UUID_FORMAT, MISSING_REQUIRED_FIELD, INVALID_SUBCATEGORY, INVALID_QUANTITY, INSUFFICIENT_BALANCE, PRICE_INCREASED, DUPLICATE_ORDER, RATE_LIMIT_EXCEEDED.

cURL
curl -s -X POST "https://api.4reply.com/freefire/orders/create" \
  -H "Authorization: Bearer YOUR_KEY_ID.YOUR_KEY_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
  "order_id": "01912345-6789-7abc-8def-0123456789ab",
  "sub_category_id": 100,
  "quantity": 1,
  "requirements": {
    "player_id": "14679257282"
  },
  "expected_unit_price": "1.070000"
}'

Response Example - 200 OK:

JSON
{
  "success": true,
  "order": {
    "order_id": "01912345-6789-7abc-8def-0123456789ab",
    "status": "pending",
    "player_id": "14679257282",
    "player_name": "ProGamer99",
    "subcategory_name": "FF 100 Diamonds",
    "quantity": 1,
    "charged_amount": "1.070000",
    "currency": "USD",
    "created_at": "2026-08-28T12:00:00.000Z"
  }
}

GET/orders/:orderId

Rate limit: 3 req / 60s per user + orderId.

Get order status and sub-transaction details by UUID.

Path Parameter Type Required Description Example
orderId string (UUID) yes Order identifier in UUID format 01912345-6789-7abc-8def-0123456789ab

Relevant errors: ORDER_NOT_FOUND, INVALID_UUID_FORMAT.

cURL
curl -s "https://api.4reply.com/freefire/orders/01912345-6789-7abc-8def-0123456789ab" \
  -H "Authorization: Bearer YOUR_KEY_ID.YOUR_KEY_SECRET"

Response Example - 200 OK:

JSON
{
  "success": true,
  "order": {
    "order_id": "01912345-6789-7abc-8def-0123456789ab",
    "status": "completed",
    "player_id": "14679257282",
    "player_name": "ProGamer99",
    "subcategory_name": "FF 100 Diamonds",
    "quantity": 1,
    "charged_amount": "1.070000",
    "currency": "USD",
    "created_at": "2026-08-28T12:00:00.000Z",
    "completed_at": "2026-08-28T12:00:04.000Z",
    "vouchers": [],
    "sub_transactions": [
      {
        "id": 1,
        "status": "completed",
        "player_id": "14679257282",
        "player_name": "ProGamer99",
        "amount": "1.070000",
        "created_at": "2026-08-28T12:00:00.000Z",
        "completed_at": "2026-08-28T12:00:04.000Z"
      }
    ]
  }
}

POST/orders/batch

Rate limit: 2 req / 60s per user.

Query status for multiple orders in a single request (up to 50 UUIDs per call).

Body Parameter Type Required Description Example
order_ids string[] yes Array of UUIDs (max 50) ["uuid-1", "uuid-2"]

Relevant errors: INVALID_ORDER_IDS_FORMAT, EMPTY_ORDER_IDS, TOO_MANY_ORDER_IDS.

cURL
curl -s -X POST "https://api.4reply.com/freefire/orders/batch" \
  -H "Authorization: Bearer YOUR_KEY_ID.YOUR_KEY_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
  "order_ids": [
    "01912345-6789-7abc-8def-0123456789ab",
    "01912345-6789-7abc-8def-0123456789ac"
  ]
}'

Response Example - 200 OK:

JSON
{
  "success": true,
  "orders": [
    {
      "order_id": "01912345-6789-7abc-8def-0123456789ab",
      "status": "completed",
      "charged_amount": "1.070000"
    }
  ],
  "not_found": [
    "01912345-6789-7abc-8def-0123456789ac"
  ]
}

GET/orders

Rate limit: 2 req / 60s per user.

Read paginated order history with filtering by status and date range.

Query Parameter Type Required Description Example
page number no Page number (default 1) 1
limit number no Results per page (1-100, default 50) 50
status string no Filter by status: pending, completed, failed, refunded, partial completed
created_after string (ISO 8601) no Orders created after this date 2026-01-01T00:00:00Z
created_before string (ISO 8601) no Orders created before this date 2026-12-31T23:59:59Z

Relevant errors: INVALID_PAGINATION, INVALID_DATE_FORMAT.

cURL
curl -s "https://api.4reply.com/freefire/orders?page=1&limit=50&status=completed" \
  -H "Authorization: Bearer YOUR_KEY_ID.YOUR_KEY_SECRET"

Response Example - 200 OK:

JSON
{
  "success": true,
  "orders": [
    {
      "order_id": "01912345-6789-7abc-8def-0123456789ab",
      "status": "completed",
      "subcategory_name": "FF 100 Diamonds",
      "quantity": 1,
      "charged_amount": "1.070000",
      "created_at": "2026-08-28T12:00:00.000Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 50,
    "total": 1,
    "total_pages": 1
  }
}

Webhooks: Order Status Callbacks

Register an HTTPS endpoint to receive final order results via POST. The callback carries the same API token as your reseller requests, in an api-token header.

This is Free Fire's own webhook, configured in the Free Fire dashboard. It keeps working unchanged and independently of the unified API's webhook_url (see the Unified API section).

Status Code Meaning & Trigger
status: 1 (accept) Order completed successfully and diamonds were delivered to the player.
status: 2 (reject) Invalid player ID only.
status: 0 Any other failure, including partial or refunded orders; message describes the reason.
webhook.test Test notification triggered manually from the dashboard.
Header Value
Content-Type application/json
api-token <keyId>.<secret> — same API token you use for reseller requests, without the Bearer prefix (or legacy ff_ key)
X-garena-Event Event name, e.g. order.completed
User-Agent garena-webhook/1.0

POST Payload - On Success (status: 1):

JSON
{
  "orderId": "01912345-6789-7abc-8def-0123456789ab",
  "message": "successfully charged 100+10 diamonds to player ProGamer",
  "status": 1
}

Node.js Express - api-token Verification & Fast Ack:

JavaScript
const crypto = require('crypto');

app.post('/reseller/webhook', express.json(), (req, res) => {
  const actual = Buffer.from(req.get('api-token') || '');
  const expected = Buffer.from(process.env.RESELLER_API_KEY_ID + '.' + process.env.RESELLER_API_SECRET);
  if (actual.length !== expected.length || !crypto.timingSafeEqual(actual, expected)) {
    return res.status(401).end();
  }
  res.status(200).end();
  processOrderAsync(req.body.orderId, req.body.status, req.body.message);
});

Delivery & Retry Behavior. Deliveries are retried on network errors, HTTP 429 and 5xx, with a 10-second timeout per attempt. Respond with HTTP 2xx promptly. The GET /orders/:orderId endpoint remains the permanent source of truth. Return 200 immediately and process tasks asynchronously in your own queue.

Idempotent Handlers. Key your webhook handler by orderId to make duplicate deliveries safe. Crediting a customer twice is far worse than a delayed notification.

To configure your webhook endpoint, generate signing secrets, and send test events, go to Configure Webhooks in your Profile on ff.4reply.com.

Rate Limits & Error Handling

Limits are published, tracked per account, and enforced on a rolling window. Every response includes X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers.

Path Requests Window Tracked Per
GET /catalog/* (all five) 80 60s per account
POST /orders/create 120 60s per account
GET /orders/:orderId 3 60s per account + order id
POST /orders/batch 2 60s per account
GET /orders 2 60s per account
GET /account 60 60s per account
POST /player/validate dedicated — per account

Throttled Response - 429 Too Many Requests:

HTTP
HTTP/1.1 429 Too Many Requests
Retry-After: 45
X-RateLimit-Limit: 80
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1765000000

{
  "success": false,
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Try again in 45 seconds.",
    "details": {
      "limit": 80,
      "remaining": 0,
      "retry_after": 45,
      "window_seconds": 60
    }
  }
}

Error Codes Reference

All error codes returned by the API, categorized with root causes and remediation steps:

Code HTTP Meaning Remediation
MISSING_API_KEY 401 Missing Authorization header Send header: Authorization: Bearer .
INVALID_API_KEY 401 API Key ID or Secret is invalid Verify Key ID and Secret or regenerate them in Profile
ACCOUNT_DISABLED 403 Account disabled by administrator Contact support to re-enable your account
ACCOUNT_FROZEN 403 Account is temporarily frozen Contact support to unfreeze your account
IP_NOT_ALLOWED 403 Source IP address is not in allowlist Add your server IP to the IP allowlist in Profile
MISSING_REQUIRED_FIELD 400 Required field missing in request body Ensure player_id and order_id are provided
INVALID_UUID_FORMAT 400 order_id format is not a valid UUID Use standard UUID format (v1, v4, v7)
INVALID_QUANTITY 400 Quantity must be an integer >= 1 Pass quantity >= 1
INVALID_CATEGORY_ID 400 Invalid category ID Use categoryId=12 for Free Fire
INVALID_BIG_CATEGORY_ID 400 Invalid big category ID Use bigCategoryId=1
INVALID_ITEM_ID 400 Invalid package item ID Use valid item IDs from the catalog
INVALID_SUBCATEGORY 400 Requested diamond package does not exist Check sub_category_id from catalog
INVALID_PRODUCT_CONFIG 400 Game requirements do not match Check required fields in requirements object
INVALID_PAGINATION 400 page or limit values out of range Pass page >= 1 and limit between 1 and 100
INVALID_DATE_FORMAT 400 Date format does not match ISO 8601 Use YYYY-MM-DDTHH:MM:SSZ format
PLAYER_NOT_FOUND 400 Player not found in Free Fire Verify the player ID is correct
PLAYER_VALIDATION_FAILED 400 Game server connection failed during validation Retry the request in a few moments
REGION_MISMATCH 400 Player region does not match expected region Ensure server and region compatibility
INSUFFICIENT_BALANCE 400 Insufficient wallet balance for this order Deposit funds to your wallet before placing orders
OUT_OF_STOCK 400 Product temporarily out of stock Retry later or choose a different package
PRICE_INCREASED 400 Current price is higher than expected_unit_price Read real-time price and update expected price
SUBCATEGORY_DISABLED 400 This product is temporarily disabled Choose a different package
DUPLICATE_ORDER 409 Order with this UUID exists with different parameters Generate a unique UUID for each new order
ORDER_NOT_FOUND 404 No order found with this UUID Verify the queried UUID is correct
ITEM_NOT_FOUND 404 Catalog item not found Query catalog to discover available IDs
ITEM_NOT_AVAILABLE 404 Item exists but is not currently purchasable Retry later
INVALID_ORDER_IDS_FORMAT 400 order_ids field must be an array of strings Pass order_ids as a string array
EMPTY_ORDER_IDS 400 order_ids array is empty Provide at least one order ID
TOO_MANY_ORDER_IDS 400 Exceeded maximum limit (50 IDs) Split request into batches of 50 or fewer
RATE_LIMIT_EXCEEDED 429 Rate limit exceeded for this endpoint Wait the Retry-After seconds before retrying
INTERNAL_ERROR 500 Unexpected internal server error Retry request or contact support
SERVICE_UNAVAILABLE 503 Service is under maintenance or overloaded Wait a few minutes and retry

Integration FAQ

How does the reseller API authenticate requests? With a single HTTP header: Authorization: Bearer <keyId>.<secret>. Key pairs are generated in your profile settings and verified on the server via HMAC on every request. No OAuth flows, cookies, or refresh tokens needed.

What is the base URL and API version my app should target? The base URL is: https://api.4reply.com/freefire (or the platform's own https://ff.4reply.com/api/endpoints/v1). Point your application directly to it for all top-up and inquiry requests.

Which field carries the idempotency key in POST /orders/create? The order_id field—a UUID you generate client-side and include in the creation body. If you resend with an existing order_id, the API returns the original order record without charging again.

My request timed out. Was the order created? Query status rather than guessing: call GET /orders/:orderId with the same UUID you sent. If the order is returned, it was created and should not be duplicated. If you get ORDER_NOT_FOUND, nothing was charged and it is safe to retry.

How do I authenticate the webhook? On your HTTPS endpoint, compare the Authorization header with the same Bearer <keyId>.<secret> token you use for API requests, using a constant-time comparison.

What should I do when I receive PRICE_INCREASED? Fetch the latest price via GET /catalog/subcategory/:itemId/price, update expected_unit_price with the new value, and resubmit using the same order_id.

What happens when I exceed a rate limit? You receive HTTP 429 with error code RATE_LIMIT_EXCEEDED and a Retry-After header. Wait the number of seconds specified in the header before retrying once.

What fields does POST /player/validate return? It returns player_name and region. Call it to display the player nickname to your buyer before confirming the top-up and to prevent ID typos.

How do I map the requirements response into the order payload? Each field_name returned by GET /catalog/category/:id/requirements should be passed as a key inside the requirements object in POST /orders/create (e.g. player_id for Free Fire).

What response is returned for requests from IPs outside the allowlist? HTTP 403 with error code IP_NOT_ALLOWED before any business logic executes. This protects your account even if credentials leak.

How long does an order take to complete? Treat completion as asynchronous; POST /orders/create returns immediately with status pending and final results arrive via webhook or subsequent polling.

Why must the API be called server-to-server only? Because API keys carry direct financial debit permissions against your wallet balance. Never expose your Key ID or Secret in a client browser or mobile app.

Platform API

Razer API

Base URLhttps://api.4reply.com/razer

The Razer Gold store API, as documented on rz.4reply.com, reachable at https://api.4reply.com/razer. Every request and answer is exactly the platform's own: only the host changes.

Base URL
Through 4Reply https://api.4reply.com/razer
Platform's own (still works) https://rz.4reply.com/api

So https://rz.4reply.com/api/get_products_categories is also https://api.4reply.com/razer/get_products_categories.

Authentication

Send your API key in the X-API-Key header of every request:

HTTP
X-API-Key: YOUR_RAZER_API_KEY
  • The API key, the API on/off switch and the API IP allowlist are on the API page of your Razer account (rz.4reply.com/api-access).
  • An active API subscription is required to send requests from outside the website, and API access must be turned on.
  • If you set an API IP allowlist, requests from other IP addresses are refused. Through 4Reply your server's IP is forwarded, so the allowlist keeps working.
cURL
curl https://api.4reply.com/razer/get_products_categories -H "X-API-Key: YOUR_RAZER_API_KEY"

Errors

A refused request answers with an HTTP error status and this body:

JSON
{
  "success": false,
  "error": {
    "error_code": "SUBSCRIPTION_REQUIRED",
    "message": "API access is not active for this account. Activate it from the API page of your account."
  },
  "error_code": "SUBSCRIPTION_REQUIRED",
  "message": "API access is not active for this account. Activate it from the API page of your account."
}

Branch on the top-level error_code and show message; error is the original error (an object, or a plain string when the error has no code, and then the top-level error_code and message are absent).

Status error_code Meaning
401 (none) Missing or wrong API key: {"success": false, "error": "Invalid or missing API key or session"}
402 SUBSCRIPTION_REQUIRED No active API subscription for this account.
403 API_DISABLED API access is turned off on the API page of your account.
403 IP_NOT_ALLOWED The calling IP is not in the account's API IP allowlist (or the list is empty).
500 internal_server_error Unexpected server error.

Endpoints

Method Path Summary
GET /health Health Check
GET /user/wallet Get User Wallet
GET /get_accounts_list Get Accounts List
POST /add_account Add Account
POST /bulk_add_accounts Bulk Add Accounts
POST /get_accounts_balances Get Accounts Balances
DELETE /delete_account/{email} Delete Account
POST /get_account_gold_balance Get Account Gold Balance
POST /get_account_silver_balance Get Account Silver Balance
GET /get_products_categories Get Products Categories
GET /get_id_products_categories Get Id Products Categories
GET /get_product_category_items/{category} Get Product Category Items
GET /get_product_category_items_in_stock/{category} Get Product Category Items In Stock
POST /reload_account_balance Reload Razer Account Balance
POST /purchase_item Purchase Item
POST /purchase_item_quantity Purchase Item Quantity
POST /purchase_id_item Purchase Id Item
POST /purchase_orders Create Purchase Order
POST /purchase_orders/{order_id}/execute Execute Purchase Order
GET /purchase_orders/{order_id} Get Purchase Order
GET /purchase_orders/{order_id}/batch_operations Get Purchase Batches Operations
POST /purchase_orders/{order_id}/stop Stop Purchase Order
POST /get_transaction_information Get Transaction Information
GET /purchase_logs Get Purchase Logs
POST /purchase_logs/lookup-by-pin Lookup Purchase Log By Pin
GET /operation_filter_options Get Operation Filter Options
GET /silver/rewards Silver Rewards
GET /silver/rewards/{reward_id}/details Silver Reward Details
POST /silver/redemptions Create Silver Redemption
GET /silver/redemptions List Silver Redemptions
GET /silver/redemptions/{redemption_id} Get Silver Redemption
POST /silver/redemptions/{redemption_id}/refresh-receipt Refresh Silver Receipt
POST /silver/redemption-batches Schedule Silver Redemption Batch
POST /silver/redemption-batches/{batch_id}/stop Stop Silver Redemption Batch
GET /pricing/public Get Public Pricing
POST /purchase-fees/quote Quote Purchase Fees
GET /account_reload_batches/{batch_id} Get Account Reload Batch

General

GET/health

Health Check

Server health check.

This endpoint can be called without an API key.

Response 200:

JSON
{
  "status": "healthy",
  "version": "2.0.0+20261017213719",
  "semantic_version": "2.0.0",
  "build_id": "20261017213719",
  "started_at": "2026-10-17T21:37:47Z",
  "message": "Razer Gold API is running",
  "api_key_required": true,
  "database_available": false,
  "note": "Every endpoint except /health needs your API key in the X-API-Key header"
}

GET/user/wallet

Get User Wallet

Your site balance (the wallet the purchase fees are taken from).

GET/get_accounts_list

Get Accounts List

List all the added accounts (without the encrypted passwords).

Parameter In Type Required Default
include_archived query boolean no false

Response 200:

JSON
{
  "total": 2,
  "accounts": [
    {
      "email": "nova.shop@example.com",
      "plain_password": "Sp!n3r2026#",
      "otp_secret": "JBSWY3DPEHPK3PXPJBSWY3DP",
      "added_at": "2026-03-12T22:18:41.102938",
      "status": "active"
    },
    {
      "email": "raid.cards@example.com",
      "plain_password": "QwEr!9065$",
      "otp_secret": "NB2W45DFOIZA====",
      "added_at": "2026-03-13T09:04:55.448821",
      "status": "processing"
    }
  ]
}

POST/add_account

Add Account

Add a new account; it is saved at once and its password and OTP are checked in the background.

  • email: the account's e-mail
  • password: the password (plain text)
  • otp_secret: the TOTP secret from Google Authenticator

If the account already exists the answer is 200 with success: false and status: "exists". Follow the check in GET /get_accounts_list.

Body (JSON):

Field Type Required Description
email string yes User email
password string yes User plain password (will be encrypted during processing)
otp_secret string yes TOTP secret key from Google Authenticator

Response 200:

JSON
{
  "success": true,
  "message": "Account added successfully.",
  "email": "wallet1@example.com",
  "status": "added"
}

POST/bulk_add_accounts

Bulk Add Accounts

Add several accounts from one text. Each account is email, then password, then otp_secret; backup codes, recovery e-mails and any e-mail not followed by a password and an OTP secret are ignored.

Body (JSON):

Field Type Required Description
raw_text string yes Raw pasted accounts text

POST/get_accounts_balances

Get Accounts Balances

Gold and Silver balances of up to 500 accounts in one call. It can take tens of seconds.

Body (JSON):

Field Type Required Description
emails string[] yes Account emails to fetch
country_code string (nullable) no Country code used for product-page proxy routing
include_silver boolean no Whether to include silver balance payloads Default true.
allow_archived boolean no Whether to allow fetching archived accounts Default false.

Example request body:

JSON
{
  "country_code": "US",
  "emails": [
    "wallet.one@example.com",
    "wallet.two@example.com"
  ],
  "include_silver": true
}

DELETE/delete_account/{email}

Delete Account

Delete an account and its saved sessions.

  • email: the account's e-mail (may be URL-encoded, %40 for @)
Parameter In Type Required Default
email path string yes

Response 200:

JSON
{
  "success": true,
  "message": "Account nova.shop@example.com deleted",
  "email": "nova.shop@example.com"
}

POST/get_account_gold_balance

Get Account Gold Balance

Get the account's balance.

  • email: the account's e-mail

Response: the balance data only (latest request).

Note: the session is saved for 24 hours to avoid logging in again.

Body (JSON):

Field Type Required Description
email string yes User email
country_code string (nullable) no Country code used for product-page proxy routing

Example request body:

JSON
{
  "country_code": "US",
  "email": "wallet1@example.com"
}

Response 200:

JSON
{
  "razerId": "RZR_077027484be382cff2d89fe0e219",
  "email": "wallet1@example.com",
  "nickname": "khaoulan8629",
  "regionId": 2,
  "walletTypeId": 0,
  "walletStatusId": 1,
  "createdDateTime": "2025-09-24T16:42:44.1283117+00:00",
  "walletGold": {
    "tier": 2,
    "premiumGold": 466.65,
    "bonusGold": 0,
    "totalGold": 466.65,
    "limit": 600,
    "currencyCode": "USD",
    "nextExpiringBonusGold": 0,
    "nextExpiringBonusGoldDateTime": "1900-01-01T00:00:00+00:00"
  },
  "walletKyc": {
    "identityTypeId": 1,
    "firstName": "Adam",
    "lastName": "White",
    "mobileNumber": "+66841308367",
    "dateOfBirth": "1995-11-08T00:00:00",
    "billingAddress1": "361 Andrew Roads Apt. 099",
    "billingAddress2": "",
    "billingZipCode": "18207",
    "billingCity": "New Elizabeth",
    "billingState": "Virginia",
    "billingCountryCode": "US"
  }
}

POST/get_account_silver_balance

Get Account Silver Balance

Get the Silver balance.

  • email: the account's e-mail

Uses the same authentication steps as the Gold balance, then calls the Silver endpoint.

Body (JSON):

Field Type Required Description
email string yes User email
country_code string (nullable) no Country code used for product-page proxy routing

Example request body:

JSON
{
  "country_code": "US",
  "email": "wallet1@example.com"
}

Response 200:

JSON
{
  "RazerId": "RZR_077027484be382cff2d89fe0e219",
  "Email": "wallet1@example.com",
  "NickName": "khaoulan8629",
  "RegionId": 2,
  "TypeId": 1,
  "StatusId": 1,
  "Disabled": 0,
  "CreatedBy": "2",
  "CreatedDateTime": "2025-09-24T16:42:44.288Z",
  "WalletSilver": {
    "Limit": 1500000,
    "PremiumSilver": 0,
    "BonusSilver": 4100,
    "NextExpiringBonusSilver": 2994,
    "NextExpiringBonusSilverDateTime": "2027-02-28T23:59:59.997Z",
    "StatusId": 1,
    "UpdatedDateTime": "2026-03-11T11:34:26.479Z",
    "Disabled": 0
  }
}

GET/get_products_categories

Get Products Categories

List the available categories.

Parameter In Type Required Default
account_email query string (nullable) no
product_type query string (nullable) no "pin"

Response 200:

JSON
{
  "categories": [
    "freefire-pins",
    "apple-card-us",
    "pubg-mobile-uc-code"
  ]
}

GET/get_id_products_categories

Get Id Products Categories

List the categories of products topped up by player ID (Direct Top-Up).

Parameter In Type Required Default
account_email query string (nullable) no

GET/get_product_category_items/{category}

Get Product Category Items

List the products available in the given category.

  • category: the category name (e.g. freefire-pins)
Parameter In Type Required Default
category path string yes
country_code query string (nullable) no
account_email query string (nullable) no
product_type query string (nullable) no

Response 200:

JSON
{
  "category": "freefire-pins",
  "products": [
    {
      "productId": 11572,
      "vanityName": "FreeFire USD 1 (100 Diamonds)",
      "unitPrice": 1.07,
      "hasStock": true
    },
    {
      "productId": 11573,
      "vanityName": "FreeFire USD 2 (210 Diamonds)",
      "unitPrice": 2.14,
      "hasStock": true
    }
  ]
}

GET/get_product_category_items_in_stock/{category}

Get Product Category Items In Stock

List the products available (in stock) in the given category.

  • category: the category name (e.g. freefire-pins)
Parameter In Type Required Default
category path string yes
country_code query string (nullable) no
account_email query string (nullable) no

Response 200:

JSON
{
  "category": "freefire-pins",
  "products": [
    {
      "id": 11572,
      "name": "FreeFire USD 1 (100 Diamonds)",
      "price": 1.07,
      "currencyCode": "USD",
      "hasStock": true,
      "permalink": "freefire-pins",
      "regionId": 2
    },
    {
      "id": 11573,
      "name": "FreeFireUSD 2 (210 Diamonds)",
      "price": 2.14,
      "currencyCode": "USD",
      "hasStock": true,
      "permalink": "freefire-pins",
      "regionId": 2
    }
  ]
}

POST/reload_account_balance

Reload Razer Account Balance

Body (JSON):

Field Type Required Description
email string yes Connected Razer account email
pin_code string (nullable) no Legacy single Razer Gold reload PIN
pin_codes string[] (nullable) no Razer Gold reload PINs, one item per input line
password string (nullable) no Password of an account that is not saved in the panel. Used for this reload only and never stored.
otp_secret string (nullable) no OTP secret of the unsaved account. Used for this reload only and never stored.

Example request body:

JSON
{
  "email": "wallet@example.com",
  "pin_codes": [
    "XXXXXXXXXXXXXX",
    "YYYYYYYYYYYYYY"
  ]
}

POST/purchase_item

Purchase Item

Buy one product from the given account and wait for the result.

  • email: the account's e-mail
  • product_id: the product number
  • product_category: the product category (e.g. freefire-pins)
  • pins_only: if true, only the PIN codes are returned

Response: the transaction details, or the PIN codes only.

Note: the session is saved for 24 hours to avoid logging in again.

Body (JSON):

Field Type Required Description
email string yes User email
product_id integer yes Product ID to purchase
product_category string yes Product category (e.g., freefire-pins)
player_id string (nullable) no Player ID for direct top-up products
pins_only boolean no If true, return only pin codes in array format Default false.
country_code string (nullable) no Country code used for product-page proxy routing
region_id integer (nullable) no Razer catalog region id for checkout
payment_channel_id integer (nullable) no Razer payment channel id for checkout
order_id string (nullable) no Client-generated purchase order identifier
batch_id string (nullable) no Client-generated batch identifier
batch_name string (nullable) no Display name for the batch
batch_sequence integer (nullable) no Batch sequence inside the order
batch_total_operations integer (nullable) no Total planned operations for the batch
batch_operation_index integer (nullable) no Current operation index inside the batch

Example request body:

JSON
{
  "batch_id": "BATCH-20260419-001",
  "batch_name": "Free Fire USD 1 (100 Diamonds)",
  "batch_operation_index": 1,
  "batch_sequence": 1,
  "batch_total_operations": 2,
  "country_code": "US",
  "email": "wallet1@example.com",
  "order_id": "ORD-20260419-001",
  "pins_only": false,
  "player_id": "14679257282",
  "product_category": "freefire-pins",
  "product_id": 11572
}

Response 200 (out of stock):

JSON
{
  "transactionNumber": "122K9T9VRNM1E0311E1E4",
  "productId": 11572,
  "regionId": 2,
  "orderStatus": 4,
  "productName": "FreeFire USD 1 (100 Diamonds)",
  "description": "FreeFire USD 1 (100 Diamonds)",
  "amount": 1.07,
  "currencyCode": "USD",
  "transactionDate": "2026-03-11T11:32:04.6280623+00:00",
  "paymentMethod": "Razer Gold",
  "isExpired": false,
  "isRazerGold": true,
  "fullfillment": {
    "rewards": [
      {
        "Title": "Spend Gold Earn Silver",
        "Description": "Spend Gold Earn Silver",
        "CreditsType": "Silver",
        "CreditsAmount": "32"
      }
    ],
    "hidePin": false
  },
  "tax": 0,
  "surcharge": 0,
  "channelId": 1,
  "paymentStatus": 1,
  "permalink": "freefire-pins",
  "productBasePrice": 1.07,
  "productTax": 0,
  "attributes": [
    {
      "key": "savePurchaseDetails",
      "value": "true"
    }
  ],
  "originalUnitPrice": 1,
  "isDynamicPricing": true,
  "iofSurcharge": 0,
  "razerSilverPaidAmount": 0,
  "status": "OUT_OF_STOCK",
  "paymentType": 2,
  "isPaidByPIN": false,
  "merchantAmountWithoutTaxInUsd": 1.07,
  "merchantTaxAmountInUsd": 0
}

Response 200 (success):

JSON
{
  "transactionNumber": "122K9T9VWE5S6D8373764",
  "productId": 16917,
  "regionId": 2,
  "orderStatus": 3,
  "productName": "Apple Card (US) - $5",
  "description": "Apple Card (US) - $5",
  "amount": 5.5,
  "currencyCode": "USD",
  "transactionDate": "2026-03-11T11:34:25.6625572+00:00",
  "paymentMethod": "Razer Gold",
  "isExpired": false,
  "isRazerGold": true,
  "fullfillment": {
    "pins": [
      {
        "serialNumber1": "69b14a1365257",
        "pinCode1": "X426L82QRKRTCJ79",
        "expiryDate": "9999-12-31"
      }
    ],
    "rewards": [
      {
        "Title": "Spend Gold Earn Silver",
        "Description": "Spend Gold Earn Silver",
        "CreditsType": "Silver",
        "CreditsAmount": "165"
      }
    ],
    "hidePin": false
  },
  "tax": 0,
  "surcharge": 0,
  "channelId": 1,
  "paymentStatus": 1,
  "permalink": "apple-card-us",
  "productBasePrice": 5.5,
  "productTax": 0,
  "attributes": [
    {
      "key": "savePurchaseDetails",
      "value": "true"
    }
  ],
  "originalUnitPrice": 5,
  "isDynamicPricing": true,
  "iofSurcharge": 0,
  "razerSilverPaidAmount": 0,
  "status": "SUCCESS",
  "paymentType": 2,
  "isPaidByPIN": false,
  "merchantAmountWithoutTaxInUsd": 5.5,
  "merchantTaxAmountInUsd": 0
}

POST/purchase_item_quantity

Purchase Item Quantity

Buy a product a given number of times (concurrent execution).

  • email: the account's e-mail
  • product_id: the product number
  • product_category: the product category (e.g. freefire-pins)
  • quantity: how many times the product is bought

Response: a list with the details of every transaction.

Steps:

  1. First and second login, once only (or a saved session)
  2. OTP verification, once only (or a saved OTP)
  3. All purchase requests run concurrently
  4. The details of every transaction are returned

Note: the session is saved for 24 hours to avoid logging in again.

Body (JSON):

Field Type Required Description
email string yes User email
product_id integer yes Product ID to purchase
product_category string yes Product category (e.g., freefire-pins)
quantity integer yes Number of items to purchase
player_id string (nullable) no Player ID for direct top-up products
pins_only boolean no If true, return only pin codes in array format Default false.
country_code string (nullable) no Country code used for product-page proxy routing

Example request body:

JSON
{
  "country_code": "US",
  "email": "wallet1@example.com",
  "pins_only": false,
  "player_id": "14679257282",
  "product_category": "freefire-pins",
  "product_id": 11572,
  "quantity": 2
}

Response 200 (bulk details):

JSON
{
  "success": true,
  "total_requested": 2,
  "successful": 2,
  "failed": 0,
  "successful_purchases": [
    {
      "attempt": 1,
      "transaction_number": "122K9T9VWE5S6D8373764",
      "details": {
        "transactionNumber": "122K9T9VWE5S6D8373764",
        "productId": 16917,
        "regionId": 2,
        "orderStatus": 3,
        "productName": "Apple Card (US) - $5",
        "description": "Apple Card (US) - $5",
        "amount": 5.5,
        "currencyCode": "USD",
        "transactionDate": "2026-03-11T11:34:25.6625572+00:00",
        "paymentMethod": "Razer Gold",
        "isExpired": false,
        "isRazerGold": true,
        "fullfillment": {
          "pins": [
            {
              "serialNumber1": "69b14a1365257",
              "pinCode1": "X426L82QRKRTCJ79",
              "expiryDate": "9999-12-31"
            }
          ],
          "rewards": [
            {
              "Title": "Spend Gold Earn Silver",
              "Description": "Spend Gold Earn Silver",
              "CreditsType": "Silver",
              "CreditsAmount": "165"
            }
          ],
          "hidePin": false
        },
        "tax": 0,
        "surcharge": 0,
        "channelId": 1,
        "paymentStatus": 1,
        "permalink": "apple-card-us",
        "productBasePrice": 5.5,
        "productTax": 0,
        "attributes": [
          {
            "key": "savePurchaseDetails",
            "value": "true"
          }
        ],
        "originalUnitPrice": 5,
        "isDynamicPricing": true,
        "iofSurcharge": 0,
        "razerSilverPaidAmount": 0,
        "status": "SUCCESS",
        "paymentType": 2,
        "isPaidByPIN": false,
        "merchantAmountWithoutTaxInUsd": 5.5,
        "merchantTaxAmountInUsd": 0,
        "success": true
      }
    },
    {
      "attempt": 2,
      "transaction_number": "122K9T9VRNM1E0311E1E4",
      "details": {
        "transactionNumber": "122K9T9VRNM1E0311E1E4",
        "productId": 11572,
        "regionId": 2,
        "orderStatus": 4,
        "productName": "FreeFire USD 1 (100 Diamonds)",
        "description": "FreeFire USD 1 (100 Diamonds)",
        "amount": 1.07,
        "currencyCode": "USD",
        "transactionDate": "2026-03-11T11:32:04.6280623+00:00",
        "paymentMethod": "Razer Gold",
        "isExpired": false,
        "isRazerGold": true,
        "fullfillment": {
          "rewards": [
            {
              "Title": "Spend Gold Earn Silver",
              "Description": "Spend Gold Earn Silver",
              "CreditsType": "Silver",
              "CreditsAmount": "32"
            }
          ],
          "hidePin": false
        },
        "tax": 0,
        "surcharge": 0,
        "channelId": 1,
        "paymentStatus": 1,
        "permalink": "freefire-pins",
        "productBasePrice": 1.07,
        "productTax": 0,
        "attributes": [
          {
            "key": "savePurchaseDetails",
            "value": "true"
          }
        ],
        "originalUnitPrice": 1,
        "isDynamicPricing": true,
        "iofSurcharge": 0,
        "razerSilverPaidAmount": 0,
        "status": "OUT_OF_STOCK",
        "paymentType": 2,
        "isPaidByPIN": false,
        "merchantAmountWithoutTaxInUsd": 1.07,
        "merchantTaxAmountInUsd": 0,
        "success": true
      }
    }
  ],
  "failed_purchases": []
}

Response 200 (pins only):

JSON
{
  "success": true,
  "total_requested": 1,
  "successful": 1,
  "failed": 0,
  "pins": [
    "X426L82QRKRTCJ79"
  ],
  "successful_purchases": [
    {
      "attempt": 1,
      "pins": [
        "X426L82QRKRTCJ79"
      ]
    }
  ],
  "failed_purchases": []
}

POST/purchase_id_item

Purchase Id Item

Top up a product by player ID (Direct Top-Up).

Body (JSON):

Field Type Required Description
email string yes User email
product_id integer yes Product ID to purchase
product_category string yes Product category (e.g., freefire-direct-top-up)
player_id string yes Player ID for direct top-up
pins_only boolean no If true, return only pin codes in array format Default false.
country_code string (nullable) no Country code used for product-page proxy routing
region_id integer (nullable) no Razer catalog region id for checkout
payment_channel_id integer (nullable) no Razer payment channel id for checkout
order_id string (nullable) no Client-generated purchase order identifier
batch_id string (nullable) no Client-generated batch identifier
batch_name string (nullable) no Display name for the batch
batch_sequence integer (nullable) no Batch sequence inside the order
batch_total_operations integer (nullable) no Total planned operations for the batch
batch_operation_index integer (nullable) no Current operation index inside the batch

POST/purchase_orders

Create Purchase Order

For large orders: saves the order plan (batches of products and quantities) without buying anything. Start it with POST /purchase_orders/{order_id}/execute.

order_id is yours to choose and must be unique; sending it again returns the same order. account_email also accepts auto to let the site pick the accounts.

Body (JSON):

Field Type Required Description
order_id string yes Unique client-generated order identifier
order_label string (nullable) no Display label for the order
account_email string yes Razer account email used by the order
country_code string (nullable) no Country code used for the order
balance_before number (nullable) no Balance before the order started
total_batches integer yes Total batches inside the order
total_operations integer yes Total planned operations inside the order
batches PurchaseOrderBatchRequest[] yes Initial batch plan
excluded_accounts string[] (nullable) no Emails of accounts excluded from auto purchases
account_quantities object (nullable) no Per-account quantity caps in auto mode
pins_only boolean no If true, return only pin codes in array format Default false.

Items of batches (PurchaseOrderBatchRequest):

Field Type Required
batch_id string yes
batch_name string yes
account_email string (nullable) no
assigned_account_email string (nullable) no
account_label string (nullable) no
account_allocations object[] (nullable) no
auto_account_selection boolean (nullable) no
source_batch_id string (nullable) no
source_batch_name string (nullable) no
product_id integer yes
product_category string yes
product_category_key string (nullable) no
player_id string (nullable) no
region_id integer (nullable) no
payment_channel_id integer (nullable) no
quantity integer yes
unit_price number (nullable) no
currency string (nullable) no
status string (nullable) no
processed integer no
successful integer no
failed integer no
pending integer no
cancelled integer no
balance_before number (nullable) no
balance_after number (nullable) no

POST/purchase_orders/{order_id}/execute

Execute Purchase Order

Start buying the order on the server. With run_in_background: true it answers at once; follow the progress with GET /purchase_orders/{order_id}.

Parameter In Type Required Default
order_id path string yes

Body (JSON):

Field Type Required Description
run_in_background boolean no If true, schedule execution on the server and return immediately Default false.
order_label string (nullable) no Optional order label used when creating the purchase order inline
account_email string (nullable) no Account email used when creating the purchase order inline
country_code string (nullable) no Country code used when creating the purchase order inline
balance_before number (nullable) no Balance snapshot before starting the purchase order
total_batches integer (nullable) no Expected number of batches in the purchase order
total_operations integer (nullable) no Expected number of operations in the purchase order
batches object[] (nullable) no Purchase batches to create and execute inline
excluded_accounts string[] (nullable) no Emails of accounts excluded from auto purchases
account_quantities object (nullable) no Per-account quantity caps in auto mode
pins_only boolean no If true, return only pin codes in array format Default false.

GET/purchase_orders/{order_id}

Get Purchase Order

Order progress: successful, failed and remaining operations per batch.

Parameter In Type Required Default
order_id path string yes

GET/purchase_orders/{order_id}/batch_operations

Get Purchase Batches Operations

The operations of the given batches with their codes. Pass comma-separated batch_ids.

Parameter In Type Required Default
order_id path string yes
batch_ids query string yes
limit_per_batch query integer no 0
offset query integer no 0
hydrate query boolean no true
refresh query boolean no false

POST/purchase_orders/{order_id}/stop

Stop Purchase Order

Stop the order at once; anything not bought yet is cancelled.

Parameter In Type Required Default
order_id path string yes

Body (JSON):

Field Type Required Description
stop_message string (nullable) no Optional stop reason shown to the user

POST/get_transaction_information

Get Transaction Information

Get one transaction's information with transaction_number and email.

The user must send the e-mail and the transaction number.

Body (JSON):

Field Type Required Description
email string yes User email
transaction_number string yes Transaction number (e.g., 122K8L773FG65D3D5A1D8)

Example request body:

JSON
{
  "email": "wallet1@example.com",
  "transaction_number": "122K8L773BP758536A6BC"
}

Response 200:

JSON
{
  "transactionNumber": "122K9T9VWE5S6D8373764",
  "productId": 16917,
  "regionId": 2,
  "orderStatus": 3,
  "productName": "Apple Card (US) - $5",
  "description": "Apple Card (US) - $5",
  "amount": 5.5,
  "currencyCode": "USD",
  "transactionDate": "2026-03-11T11:34:25.6625572+00:00",
  "paymentMethod": "Razer Gold",
  "isExpired": true,
  "isRazerGold": true,
  "fullfillment": {
    "pins": [
      {
        "serialNumber1": "69b14a1365257",
        "pinCode1": "X426L82QRKRTCJ79",
        "expiryDate": "9999-12-31"
      }
    ],
    "rewards": [
      {
        "Title": "Spend Gold Earn Silver",
        "Description": "Spend Gold Earn Silver",
        "CreditsType": "Silver",
        "CreditsAmount": "165"
      }
    ],
    "hidePin": false
  },
  "tax": 0,
  "surcharge": 0,
  "channelId": 1,
  "paymentStatus": 1,
  "permalink": "apple-card-us",
  "productBasePrice": 5.5,
  "productTax": 0,
  "attributes": [
    {
      "key": "savePurchaseDetails",
      "value": "true"
    }
  ],
  "originalUnitPrice": 5,
  "isDynamicPricing": true,
  "iofSurcharge": 0,
  "razerSilverPaidAmount": 0,
  "status": "SUCCESS",
  "paymentType": 2,
  "isPaidByPIN": false,
  "merchantAmountWithoutTaxInUsd": 5.5,
  "merchantTaxAmountInUsd": 0,
  "_source": "razer"
}

GET/purchase_logs

Get Purchase Logs

Your purchases with their codes, filtered by account, order or transaction number.

Parameter In Type Required Default
account_email query string (nullable) no
limit query integer no 50
offset query integer no 0
transaction_number query string (nullable) no
order_id query string (nullable) no
batch_id query string (nullable) no
main_category query string (nullable) no
sub_category query string (nullable) no
display_status query string (nullable) no
financial_type query string (nullable) no
hydrate query boolean no true

Response 200:

JSON
{
  "success": true,
  "total": 8,
  "purchases": [
    {
      "id": 8,
      "username": "YZ9CZ",
      "account_email": "wallet1@example.com",
      "product_id": 16917,
      "product_category": "apple-card-us",
      "quantity": 1,
      "transaction_number": "122K9T9VWE5S6D8373764",
      "status": "success",
      "pins_json": "[]",
      "request_payload_json": "{\"email\": \"wallet1@example.com\", \"product_id\": 16917, \"product_category\": \"apple-card-us\", \"pins_only\": false}",
      "response_payload_json": "{\"transactionNumber\": \"122K9T9VWE5S6D8373764\", \"productId\": 16917, \"regionId\": 2, \"orderStatus\": 3, \"productName\": \"Apple Card (US) - $5\", \"description\": \"Apple Card (US) - $5\", \"amount\": 5.5, \"currencyCode\": \"USD\", \"transactionDate\": \"2026-03-11T11:34:25.6625572+00:00\", \"paymentMethod\": \"Razer Gold\", \"isExpired\": false, \"isRazerGold\": true, \"fullfillment\": {\"pins\": [{\"serialNumber1\": \"69b14a1365257\", \"serialNumber2\": null, \"serialNumber3\": null, \"pinCode1\": \"X426L82QRKRTCJ79\", \"pinCode2\": null, \"pinCode3\": null, \"expiryDate\": \"9999-12-31\"}], \"rewards\": [{\"Title\": \"Spend Gold Earn Silver\", \"Description\": \"Spend Gold Earn Silver\", \"CreditsType\": \"Silver\", \"CreditsAmount\": \"165\"}], \"hidePin\": false}, \"tax\": 0, \"surcharge\": 0, \"channelId\": 1, \"paymentStatus\": 1, \"permalink\": \"apple-card-us\", \"productBasePrice\": 5.5, \"productTax\": 0, \"attributes\": [{\"key\": \"savePurchaseDetails\", \"value\": \"true\"}], \"originalUnitPrice\": 5, \"isDynamicPricing\": true, \"iofSurcharge\": 0, \"razerSilverPaidAmount\": 0, \"status\": \"SUCCESS\", \"paymentType\": 2, \"isPaidByPIN\": false, \"merchantAmountWithoutTaxInUsd\": 5.5, \"merchantTaxAmountInUsd\": 0}",
      "created_at": "2026-03-11T11:34:28",
      "pins": [],
      "request_payload": {
        "email": "wallet1@example.com",
        "product_id": 16917,
        "product_category": "apple-card-us",
        "pins_only": false
      },
      "response_payload": {
        "transactionNumber": "122K9T9VWE5S6D8373764",
        "productId": 16917,
        "regionId": 2,
        "orderStatus": 3,
        "productName": "Apple Card (US) - $5",
        "description": "Apple Card (US) - $5",
        "amount": 5.5,
        "currencyCode": "USD",
        "transactionDate": "2026-03-11T11:34:25.6625572+00:00",
        "paymentMethod": "Razer Gold",
        "isExpired": false,
        "isRazerGold": true,
        "fullfillment": {
          "pins": [
            {
              "serialNumber1": "69b14a1365257",
              "pinCode1": "X426L82QRKRTCJ79",
              "expiryDate": "9999-12-31"
            }
          ],
          "rewards": [
            {
              "Title": "Spend Gold Earn Silver",
              "Description": "Spend Gold Earn Silver",
              "CreditsType": "Silver",
              "CreditsAmount": "165"
            }
          ],
          "hidePin": false
        },
        "tax": 0,
        "surcharge": 0,
        "channelId": 1,
        "paymentStatus": 1,
        "permalink": "apple-card-us",
        "productBasePrice": 5.5,
        "productTax": 0,
        "attributes": [
          {
            "key": "savePurchaseDetails",
            "value": "true"
          }
        ],
        "originalUnitPrice": 5,
        "isDynamicPricing": true,
        "iofSurcharge": 0,
        "razerSilverPaidAmount": 0,
        "status": "SUCCESS",
        "paymentType": 2,
        "isPaidByPIN": false,
        "merchantAmountWithoutTaxInUsd": 5.5,
        "merchantTaxAmountInUsd": 0
      }
    }
  ]
}

POST/purchase_logs/lookup-by-pin

Lookup Purchase Log By Pin

Body (JSON):

Field Type Required Description
pin string yes Full or partial purchase PIN used only for the authenticated lookup

GET/operation_filter_options

Get Operation Filter Options

Return distinct filters for the user's complete operation-history scope.

Parameter In Type Required Default
source query string no "dashboard"
account_email query string (nullable) no
order_id query string (nullable) no
batch_id query string (nullable) no

GET/silver/rewards

Silver Rewards

GET/silver/rewards/{reward_id}/details

Silver Reward Details

Parameter In Type Required Default
reward_id path integer yes
account_email query string yes
country_code query string (nullable) no

POST/silver/redemptions

Create Silver Redemption

Body (JSON):

Field Type Required Description
account_email string yes
local_reward_id integer yes
client_request_id string yes
batch_id string (nullable) no
batch_name string (nullable) no
batch_sequence integer (nullable) no
batch_total_operations integer (nullable) no
batch_operation_index integer (nullable) no
scheduled_redemption_id integer (nullable) no
country_code string (nullable) no Country code used for proxy routing
max_amount integer (nullable) no Do not redeem when the live Silver price is above this amount
min_remaining_balance integer (nullable) no Bonus Silver that must stay on the account after this redemption

GET/silver/redemptions

List Silver Redemptions

Parameter In Type Required Default
page query integer no 1
page_size query integer no 20
status query string (nullable) no
account_email query string (nullable) no
search query string (nullable) no
batch_id query string (nullable) no
start_date query string (nullable) no
end_date query string (nullable) no

GET/silver/redemptions/{redemption_id}

Get Silver Redemption

Parameter In Type Required Default
redemption_id path integer yes

POST/silver/redemptions/{redemption_id}/refresh-receipt

Refresh Silver Receipt

Parameter In Type Required Default
redemption_id path integer yes

POST/silver/redemption-batches

Schedule Silver Redemption Batch

Body (JSON):

Field Type Required Description
batch_id string yes
batch_name string yes
country_code string (nullable) no
operations SilverScheduledOperation[] yes

Items of operations (SilverScheduledOperation):

Field Type Required
account_email string yes
local_reward_id integer yes
client_request_id string yes
batch_operation_index integer yes
expected_amount integer (nullable) no
max_amount integer (nullable) no
min_remaining_balance integer (nullable) no

POST/silver/redemption-batches/{batch_id}/stop

Stop Silver Redemption Batch

Parameter In Type Required Default
batch_id path string yes

Body (JSON):

Field Type Required Description
stop_message string (nullable) no

GET/pricing/public

Get Public Pricing

The prices this customer pays: the site-wide prices with any the admin set for them alone (customer_prices) in their place.

POST/purchase-fees/quote

Quote Purchase Fees

The commission each line of a cart will be charged.

Body (JSON):

Field Type Required Description
items FeeQuoteItem[] no

Items of items (FeeQuoteItem):

Field Type Required
product_id integer (nullable) no
product_category string (nullable) no
unit_price number (nullable) no
quantity integer no

Account reload history

GET/account_reload_batches/{batch_id}

Get Account Reload Batch

Parameter In Type Required Default
batch_id path string yes

Platform API

ShamCash API

Base URLhttps://api.4reply.com/shamcash

The ShamCash API, as documented on shamcash.4reply.com (translated to English), reachable at https://api.4reply.com/shamcash. Requests and answers are exactly the platform's own: only the host changes.

Base URL
Through 4Reply https://api.4reply.com/shamcash
Platform's own (still works) https://shamcash.4reply.com/api

Every path below is relative to the base URL, e.g. POST https://api.4reply.com/shamcash/account/history/search.

Connection details

Send the key in the header of every request and do not share it.

API key the X-API-Key header, e.g. X-API-Key: sham_xxxxxxxxxxxxxxxxx
Base URL https://api.4reply.com/shamcash (or https://shamcash.4reply.com/api)
  • Generating a new key stops the current key immediately; you will need to update it in your connected systems.
  • Each section needs one of the two paid API activations of your ShamCash account:
  • Payment-check API ("API فحص الحوالات التلقائي", the automatic transfer check API): the operation queries below.
  • Payments API: transfers, Syriatel, MTN, electronic payments and the additional services.
  • Store products work with either activation.
  • When the trial period has ended and the API is not activated, requests answer with the code API_SUBSCRIPTION_REQUIRED. Through 4Reply your server's IP is forwarded, so an API IP allowlist keeps working.
cURL
curl https://api.4reply.com/shamcash/account/history -H "X-API-Key: sham_xxxxxxxxxxxxxxxxx"

Common error answers (result: 400, succeeded: false):

JSON
{"result": 400, "succeeded": false, "data": null, "message": "Insufficient balance to complete the transaction"}
JSON
{"result": 400, "succeeded": false, "data": null, "message": "Phone number is incorrect."}
JSON
{"result": 400, "succeeded": false, "data": null, "message": "Bill information is incorrect or cannot be paid right now."}
JSON
{"result": 400, "succeeded": false, "data": null, "message": "The service is stopped by the provider."}

Store products

Works with either API activation.

One link returns every sellable service as a separate product (money transfer per currency, Syriatel and MTN top-up, bills and cash, every MTN bundle, and every electronic-payment biller), to add the products to any store automatically instead of adding them by hand. Each product contains its fields (fields), its pricing (pricing) and the request that executes it (order); products with flow = inquiry_then_pay need an inquiry (inquiry) before paying. The transfer check service is not a product. Filter with ?category=transfer|mobile|electronic.

GET/store/products

All products: returns the categories and every product with how to execute it.

Example response:

JSON
{
  "success": true,
  "api_base_url": "https://shamcash.4reply.com/api",
  "auth": {"header": "X-API-Key"},
  "count": 40,
  "categories": [
    {"id": "mobile", "name_ar": "مدفوعات الخليوي", "name_en": "Mobile payments",
     "subcategories": [{"id": "mtn-bundles", "name_ar": "تفعيل باقات MTN", "name_en": "MTN bundles"}]}
  ],
  "data": [
    {
      "id": "mtn-bundle-3863",
      "name": "MTN - باقة مسبق الدفع اليومية 1",
      "name_en": "MTN - Daily Plan 1",
      "description_ar": "2 غيغابايت انترنت + 100 دقيقة + 100 رسالة (يومية)",
      "category": {"id": "mobile", "name_ar": "مدفوعات الخليوي"},
      "subcategory": {"id": "mtn-bundles", "name_ar": "تفعيل باقات MTN"},
      "icon": "https://shamcash.4reply.com/service-icons/mtn1.png",
      "available": true,
      "fields": [{"key": "phoneNumber", "label_ar": "رقم الهاتف", "type": "phone", "required": true, "pattern": "^09(4|5|6)\\d{7}$"}],
      "pricing": {"type": "fixed", "currency": "SYP", "price": "62.4", "base_price": "60"},
      "flow": "direct",
      "order": {"method": "POST", "path": "/api/mtn/bundles/activate", "body": {"phoneNumber": "{phoneNumber}", "bundleId": "3863"}}
    },
    {
      "id": "syriatel-units",
      "name": "تحويل وحدات سيريتل",
      "pricing": {"type": "custom_amount", "currency": "SYP", "min_amount": 100, "cost_formula": "ceil(amount * 1.04)"},
      "flow": "direct",
      "order": {"method": "POST", "path": "/api/syriatel/prepaid/recharge", "body": {"phoneNumber": "{phoneNumber}", "amount": "{amount}"}}
    }
  ]
}

Placeholders in order.body / inquiry.body are written {fieldKey}; {amount} is the amount you charge and {inquiry.x} a value returned by the inquiry. The paths in order.path are relative to the ShamCash site root and start with /api; through 4Reply drop that /api: /api/mtn/bundles/activate is https://api.4reply.com/shamcash/mtn/bundles/activate.

GET/store/products/{product_id}

One product: returns one product by its id, such as mtn-bundle-3863, syriatel-units or biller-22.

Example: GET /store/products/mtn-units

JSON
{"success": true, "data": {"id": "mtn-units", "name": "تحويل وحدات MTN", "pricing": {"type": "custom_amount", "currency": "SYP", "min_amount": 10, "step": 10}}}

Operation queries (payment check)

Requires the payment-check API activation ("API فحص الحوالات التلقائي").

Requests that read the operation history and look up a specific operation, used to confirm the transfers you receive. In the unified API this is the payments service type.

GET/account/history

Last 10 operations: fetches the last 10 operations of the account history.

JSON
{
  "result": 200,
  "succeeded": true,
  "data": {
    "haveNext": true,
    "havePrevious": false,
    "page": 1,
    "limit": 10,
    "count": 1,
    "log": [
      {
        "tranId": 150010700,
        "tranKind": 1,
        "accountId": 0,
        "accountNumber": "************1883",
        "userName": "اسم حساب المستلم",
        "amount": 5,
        "currencyId": 2,
        "currencyName": "SYP",
        "tranDate": "2026-03-17",
        "tranTime": "03:48:05",
        "peerAccountNumber": "************5880",
        "peerUserName": "اسم حساب المرسل",
        "peerAccountAddress": "عنوان حساب المرسل",
        "isHidden": false,
        "note": "",
        "isVerified": false,
        "peerAccountType": null
      }
    ]
  },
  "message": "History loaded successfully."
}

POST/account/history/search

Search by operation number: looks up one operation by its operation number.

Field Label Required
tranId Operation number yes

Example request body:

JSON
{"tranId": "467283577"}

Example response:

JSON
{
  "ok": true,
  "message": "Transaction loaded successfully.",
  "data": {
    "tranId": 467283577,
    "strTranId": "467283577",
    "tranKind": 1,
    "accountId": 0,
    "accountNumber": "************5344",
    "userName": "اسم حساب المستلم",
    "amount": 22.0,
    "currencyId": 1,
    "currencyName": "USD",
    "tranDate": "2026-09-21",
    "tranTime": "17:56:07",
    "peerAccountNumber": "************9334",
    "peerUserName": "اسم حساب المرسل",
    "peerAccountAddress": "f9a5242a7e75c8e54d3afbf3183fa228",
    "isHidden": false,
    "note": "",
    "isVerified": false,
    "peerAccountType": null
  },
  "result_code": 200
}

Not Found (404):

JSON
{"ok": false, "message": "Transaction not found.", "data": {}, "result_code": 404}

POST/account/history/filter

Filter operations: filters the account's operations by operation number (tranId), the other party's account address (peerAccount), the currency (currency or currencyId) or a date range (startDate and endDate, format YYYY-MM-DD). At least one criterion is required, and several can be combined. Without dates the range from 2000-01-01 to today is used, and every matching operation is returned at once. Leave out the fields you do not fill in.

Field Label Required
tranId Operation number no
peerAccount Other party's account address no
currency Currency: SYP (Syrian pound) or USD (dollar); empty for all currencies no
startDate From date no
endDate To date no

Example request body:

JSON
{"peerAccount": "e73579e5aa7300a863bfd4899ab2fb2f", "currency": "SYP"}

Example response:

JSON
{
  "succeeded": true,
  "ok": true,
  "message": "Transactions loaded successfully.",
  "data": [
    {
      "tranId": 487501272,
      "strTranId": "487501272",
      "tranKind": 1,
      "accountId": 0,
      "accountNumber": "************5344",
      "userName": "اسم حساب المستلم",
      "amount": 150000,
      "currencyId": 2,
      "currencyName": "SYP",
      "tranDate": "2026-07-14",
      "tranTime": "11:20:45",
      "peerAccountNumber": "************9334",
      "peerUserName": "اسم حساب الطرف الآخر",
      "peerAccountAddress": "e73579e5aa7300a863bfd4899ab2fb2f",
      "isHidden": false,
      "note": "",
      "isVerified": false,
      "peerAccountType": null
    }
  ],
  "result_code": 200,
  "result": 200
}

Missing Filter (400):

JSON
{
  "succeeded": false,
  "ok": false,
  "message": "At least one filter is required: tranId, peerAccount, currency/currencyId, or a startDate/endDate range.",
  "data": {},
  "result_code": 400,
  "result": 400
}

Money transfer

Requires the payments API activation.

A request to transfer an amount to another ShamCash account.

POST/transaction/new

Create a new operation: sends an amount to the given account.

Field Label Required
amount Amount yes
currency Currency: SYP (Syrian pound) or USD (dollar) yes
accountAddress Account address yes
confirmCode Transfer protection code (optional, digits only) no
isHidden Transfer under a hidden name (true/false; default false, name shown) no

Example request body:

JSON
{"amount": 5, "currency": "SYP", "accountAddress": "account-address", "confirmCode": "0935", "isHidden": false}

Example response:

JSON
{"result": 2000, "succeeded": true, "data": null, "optionalUpgrade": false, "message": "Successfully"}

Insufficient Balance:

JSON
{"result": 400, "succeeded": false, "data": null, "message": "Insufficient balance to complete the transaction"}

Account Not Found:

JSON
{"result": 400, "succeeded": false, "data": null, "message": "The account does not exist."}

Syriatel

Requires the payments API activation.

Syriatel top-up, postpaid bills and Syriatel Cash.

POST/syriatel/prepaid

Syriatel prepaid: tops up a Syriatel prepaid line.

Field Label Required
PhoneNumber Phone number yes
amount Amount (minimum 100) yes

Example request body:

JSON
{"PhoneNumber": "0933333333", "amount": 100}

Example response:

JSON
{"result": 2000, "succeeded": true, "data": {"transactionId": "500004028757661"}, "message": "Successfully"}

Other answers: Phone Number Incorrect, Insufficient Balance (see above), and Amount Less Than 100:

JSON
{"result": 400, "succeeded": false, "message": "Syriatel amount must be at least 100.", "data": null}

POST/syriatel/prepaid/calculate-paid-amount

Calculate the top-up value: calculates the net amount and fees of a Syriatel prepaid top-up.

Field Label Required
PhoneNumber Phone number yes
amount Amount yes

Example request body:

JSON
{"PhoneNumber": "0933333333", "amount": 100}

Example response:

JSON
{"result": 2000, "succeeded": true, "data": {"amount": 100, "paidAmount": 100}, "message": "Successfully"}

POST/syriatel/postpaid

Syriatel postpaid: pays a Syriatel postpaid line.

Field Label Required
PhoneNumber Phone number yes
amount Amount yes

Example request body:

JSON
{"PhoneNumber": "0933333333", "amount": 100}

Example response:

JSON
{"result": 2000, "succeeded": true, "data": {"transactionId": "500004028757661"}, "message": "Successfully"}

Other answers: Phone Number Incorrect, Insufficient Balance.

POST/syriatel/cash

Syriatel Cash: deposits into a Syriatel Cash wallet.

Field Label Required
PhoneNumber Phone number yes
amount Amount (100 to 5500) yes

Example request body:

JSON
{"PhoneNumber": "0933333333", "amount": 100}

Example response:

JSON
{"result": 2000, "succeeded": true, "data": {"transactionId": "800000031034480"}, "message": "Successfully"}

Other answers: Phone Number Incorrect, Insufficient Balance, and Amount Out Of Range:

JSON
{"result": 400, "succeeded": false, "message": "Cash amount must be between 100 and 5500.", "data": null}

MTN

Requires the payments API activation.

MTN top-up, postpaid bills, MTN Cash and MTN bundle activation.

POST/mtn/prepaid

MTN prepaid: tops up an MTN prepaid line.

Field Label Required
PhoneNumber Phone number yes
amount Amount (a multiple of 10) yes

Example request body:

JSON
{"PhoneNumber": "0944444444", "amount": 10}

Example response:

JSON
{"result": 2000, "succeeded": true, "data": {"transactionId": "91692521"}, "message": "Successfully"}

Other answers: Phone Number Incorrect, Insufficient Balance, and Amount Invalid:

JSON
{"result": 400, "succeeded": false, "message": "MTN amount must be a multiple of 10.", "data": null}

POST/mtn/postpaid

MTN postpaid: pays an MTN postpaid line.

Field Label Required
PhoneNumber Phone number yes
amount Amount yes

Example request body:

JSON
{"PhoneNumber": "0944444444", "amount": 100}

Example response:

JSON
{"result": 2000, "succeeded": true, "data": {"transactionId": "500004028757661"}, "message": "Successfully"}

Other answers: Phone Number Incorrect, Insufficient Balance.

POST/mtn/cash

MTN Cash: deposits into an MTN Cash wallet.

Field Label Required
PhoneNumber Phone number yes
amount Amount (100 to 5500) yes

Example request body:

JSON
{"PhoneNumber": "0944444444", "amount": 100}

Example response:

JSON
{"result": 2000, "succeeded": true, "data": {"transactionId": "36479184"}, "message": "Successfully"}

Other answers: Phone Number Incorrect, Insufficient Balance, and Amount Out Of Range:

JSON
{"result": 400, "succeeded": false, "message": "Cash amount must be between 100 and 5500.", "data": null}

GET/mtn/bundles

MTN bundles: shows the available MTN bundles grouped by duration. paidAmount is the amount deducted (the price with tax), and bundleId is what you send when activating.

JSON
{
  "result": 2500,
  "succeeded": true,
  "data": {
    "prePaid": [
      {
        "enDuration": "Daily",
        "arDuration": "يومية",
        "bundles": [
          {
            "bundleId": "3863",
            "bundleType": "Prepaid",
            "bundleArName": "باقة مسبق الدفع اليومية 1",
            "bundleEnName": "Daily Plan 1",
            "bundleArDescription": "2 غيغابايت انترنت + 100 دقيقة + 100 رسالة",
            "bundleEnDescription": "2 GB data + 100 minutes + 100 SMS",
            "bundlePrice": "60",
            "paidAmount": "62.4",
            "activated": "1"
          }
        ]
      }
    ],
    "postPaid": []
  },
  "message": "Successfully"
}

POST/mtn/bundles/activate

Activate an MTN bundle: activates an MTN bundle on a number. The bundle's paidAmount is deducted from the Syrian pound balance.

Field Label Required
phoneNumber MTN number yes
bundleId Bundle number (bundleId) yes

Example request body:

JSON
{"phoneNumber": "0944444444", "bundleId": "3863"}

Example response:

JSON
{"result": 2000, "succeeded": true, "data": {"transactionId": "91692522"}, "message": "Successfully"}

Other answers: Phone Number Incorrect, Insufficient Balance.

Electronic payments

Requires the payments API activation.

Inquiry and payment of electricity and landline bills.

POST/billing/electricity/presentment

Electricity bill inquiry: looks up the electricity bill by governorate, subscription number and billing number.

Field Label Required
gov Governorate: Hama, Damascus, Rural Damascus, Homs, Tartous, Latakia, Idlib, Aleppo, Raqqa, Al-Hasakah, Deir ez-Zor, As-Suwayda, Daraa, Quneitra yes
subscription Subscription number yes
billingno Billing number yes

Example request body:

JSON
{"gov": "Homs", "subscription": "349034", "billingno": "248667"}

Example response:

JSON
{
  "result": 2000,
  "succeeded": true,
  "data": [
    [
      {"nameAr": "رقم الفوترة", "nameEn": "Billing No", "key": "billing_no", "value": "03_248667_349034"},
      {"nameAr": "رقم الفاتورة", "nameEn": "Bill No", "key": "bill_no", "value": "68839134"},
      {"nameAr": "المبلغ", "nameEn": "Amount", "key": "amount", "value": "19217.61"},
      {"nameAr": "العملة", "nameEn": "Currency", "key": "currency", "value": "SYP"},
      {"nameAr": "ملاحظة", "nameEn": "Note", "key": "note", "value": "اسم المشترك:جورج عبدي ايليا,الدورة:202506"}
    ]
  ],
  "message": "Successfully"
}

No Bills:

JSON
{"result": 400, "succeeded": false, "data": null, "message": "No bills found"}

Wrong Payment Code:

JSON
{"result": 400, "succeeded": false, "data": null, "message": "The Payment code is incorrect. Please check and try again."}

POST/billing/electricity/pay

Pay an electricity bill: pays the electricity bill with the bill data shown by the inquiry.

Field Label Required
gov Governorate yes
billingno Billing number yes
subscription Subscription number yes
bill_no Bill number yes
amount Amount yes
note Note yes

Example request body:

JSON
{"gov": "Homs", "billingno": "248667", "subscription": "349034", "bill_no": "68839134", "amount": "19215", "note": "اسم المشترك:جورج عبدي ايليا,الدورة:202506"}

Example response:

JSON
{"result": 2000, "succeeded": true, "data": {"transactionId": "36479254"}, "message": "Successfully"}

Other answers: Unpayable Bill, Insufficient Balance (see above).

POST/billing/syrian-telecom/presentment

Landline bill inquiry: looks up the landline bills by phone number.

Field Label Required
phone Phone number yes

Example request body:

JSON
{"phone": "0186589536"}

Example response:

JSON
{
  "result": 2000,
  "succeeded": true,
  "data": [
    [
      {"nameAr": "رقم الفوترة", "nameEn": "Billing No", "key": "billing_no", "value": "0182228248"},
      {"nameAr": "رقم الفاتورة", "nameEn": "Bill No", "key": "bill_no", "value": "3145743185"},
      {"nameAr": "المبلغ", "nameEn": "Amount", "key": "amount", "value": "100"},
      {"nameAr": "التاريخ", "nameEn": "Date", "key": "date", "value": "2026-04-30"},
      {"nameAr": "ملاحظة", "nameEn": "Note", "key": "note", "value": "0182228248 / 202601"}
    ],
    [
      {"nameAr": "رقم الفوترة", "nameEn": "Billing No", "key": "billing_no", "value": "0182228248"},
      {"nameAr": "رقم الفاتورة", "nameEn": "Bill No", "key": "bill_no", "value": "3162245497"},
      {"nameAr": "المبلغ", "nameEn": "Amount", "key": "amount", "value": "100"},
      {"nameAr": "التاريخ", "nameEn": "Date", "key": "date", "value": "2026-04-30"},
      {"nameAr": "ملاحظة", "nameEn": "Note", "key": "note", "value": "0182228248 / 202602"}
    ]
  ],
  "message": "Successfully"
}

Other answers: No Bills, Provider Unavailable (see above).

POST/billing/syrian-telecom/pay

Pay a landline bill: pays the landline bill with the bill data shown by the inquiry.

Field Label Required
phone Phone number yes
bill_no Bill number yes
amount Amount yes
date Date yes
note Note yes

Example request body:

JSON
{"phone": "0182228248", "bill_no": "3145743185", "amount": "100", "date": "2026-04-30", "note": "0182228248 / 202601"}

Example response:

JSON
{"result": 2000, "succeeded": true, "data": {"transactionId": "36479254"}, "message": "Successfully"}

Other answers: Unpayable Bill, Insufficient Balance.

Additional services

Requires the payments API activation.

General bills for any provider (serviceId), plus education and university services, electronic payment and green energy. Each service's fields are set by the provider: use the services catalog to find the serviceId values, then "billing fields" or the inquiry to find the required fields, then pay with the same values array.

GET/service/catalog

Services catalog: shows the available services and providers with each service's serviceId.

JSON
{
  "result": 2000,
  "succeeded": true,
  "data": [
    {"serviceId": 39, "nameAr": "كهرباء", "nameEn": "Electricity"},
    {"serviceId": 41, "nameAr": "الهاتف الأرضي", "nameEn": "Landline"}
  ],
  "message": "Successfully"
}

POST/billing/fields?serviceId=73

Billing fields: returns the fields a provider requires. Pass serviceId in the path.

Example request body:

JSON
{}

Example response:

JSON
{"result": 2000, "succeeded": true, "data": [{"nameAr": "رقم الفوترة", "nameEn": "Billing No", "key": "billingno", "value": ""}], "message": "Successfully"}

POST/billing/presentment?serviceId=73

General bill inquiry: looks up a bill of any provider. Pass serviceId in the path and the provider's fields in a values array.

Example request body:

JSON
{"values": [{"key": "billingno", "value": "248667"}]}

Example response:

JSON
{
  "result": 2000,
  "succeeded": true,
  "data": [
    [
      {"nameAr": "رقم الفوترة", "nameEn": "Billing No", "key": "billing_no", "value": "248667"},
      {"nameAr": "رقم الفاتورة", "nameEn": "Bill No", "key": "bill_no", "value": "68839134"},
      {"nameAr": "المبلغ", "nameEn": "Amount", "key": "amount", "value": "19217.61"}
    ]
  ],
  "message": "Successfully"
}

Other answers: No Bills.

POST/billing/pay?serviceId=73

General bill payment: pays a bill of any provider. Pass serviceId in the path and the bill fields shown by the inquiry (with the amount) in values.

Example request body:

JSON
{"values": [{"key": "billing_no", "value": "68839134"}, {"key": "amount", "value": "19215"}]}

Example response:

JSON
{"result": 2000, "succeeded": true, "data": {"transactionId": "36479254"}, "message": "Successfully"}

Other answers: Unpayable Bill, Insufficient Balance.

GET/education/services

Education services: shows the available education and university services.

JSON
{"result": 2000, "succeeded": true, "data": [], "message": "Successfully"}

POST/education/presentment

Education inquiry: looks up the fees of an education service. The fields depend on the service chosen from the education catalog.

Example request body:

JSON
{"values": [{"key": "number", "value": "123456"}]}

Example response:

JSON
{"result": 2000, "succeeded": true, "data": [], "message": "Successfully"}

POST/education/pay

Education payment: pays the fees of an education service after the inquiry. Pass the shown fields (with the amount) in values.

Example request body:

JSON
{"values": [{"key": "number", "value": "123456"}, {"key": "amount", "value": "50000"}]}

Example response:

JSON
{"result": 2000, "succeeded": true, "data": {"transactionId": "36479260"}, "message": "Successfully"}

Other answers: Insufficient Balance.

POST/electronic-payment/bill

Electronic payment inquiry: looks up a bill at the electronic-payment provider. The fields depend on the provider.

Example request body:

JSON
{"values": [{"key": "billNo", "value": "123456"}]}

Example response:

JSON
{"result": 2000, "succeeded": true, "data": [], "message": "Successfully"}

POST/electronic-payment/pay

Electronic payment: pays a bill at the electronic-payment provider after the inquiry. Pass the fields (with the amount) in values.

Example request body:

JSON
{"values": [{"key": "billNo", "value": "123456"}, {"key": "amount", "value": "10000"}]}

Example response:

JSON
{"result": 2000, "succeeded": true, "data": {"transactionId": "36479262"}, "message": "Successfully"}

Other answers: Insufficient Balance.

GET/green-energy/services

Green energy services: shows the available green energy services.

JSON
{"result": 2000, "succeeded": true, "data": [], "message": "Successfully"}

POST/green-energy/fees

Fees and dues: looks up the fees and dues of a green energy service. The fields depend on the service.

Example request body:

JSON
{"values": [{"key": "number", "value": "123456"}]}

Example response:

JSON
{"result": 2000, "succeeded": true, "data": [], "message": "Successfully"}

POST/green-energy/pay

Green energy payment: pays the dues of a green energy service after the inquiry. Pass the fields (with the amount) in values.

Example request body:

JSON
{"values": [{"key": "number", "value": "123456"}, {"key": "amount", "value": "25000"}]}

Example response:

JSON
{"result": 2000, "succeeded": true, "data": {"transactionId": "36479264"}, "message": "Successfully"}

Other answers: Insufficient Balance.

Request paths used by the store products

The store-products catalog points some products at these request paths (same platform endpoints, other spellings); they are reachable the same way:

POST /syriatel/prepaid/recharge, POST /syriatel/postpaid/charge, POST /syriatel/cash-in, POST /mtn/prepaid/recharge, POST /mtn/postpaid/charge, POST /mtn/cash-in, POST /billing/landline/presentment, POST /billing/landline/pay, POST /green-energy/pay-by-type.

4Reply API · version 2.0.0 · Swagger · OpenAPI