🌐 Language
🇹🇯 Tajik🇷🇺 Russian🇬🇧 English

GamesDrop API Documentation

# GamesDrop API — Official Documentation (English) ## 1. Overview The API connects bots, applications, and partner stores to GamesDrop. All responses use JSON. - Base URL: `https://gamesdrop.org/api/v1` - Authentication: `Authorization: Bearer GD_API_KEY` (the key looks like `gd_live_xxxxxxxxxxxx.secret`) - Content-Type: `application/json` - Send requests from your server. Never expose the API key in a browser or client-side application. - Order creation requires an `Idempotency-Key` header: 8–128 printable ASCII characters (a UUID is recommended). Use a new key for every new order. Keep the same key only when safely retrying the exact same request. - Every response includes an `X-Request-Id` header. Send it to support when reporting a problem. - The `error` text is human-readable and may be in Tajik. Always build your logic on the `code` field and the HTTP status, never on the text. ## 2. Get an API key Open the **API** section in your GamesDrop account and create a key. The full value is displayed only once. Store it in your server environment. If it is exposed, revoke it and create a replacement. ## 3. Catalog and pricing Category IDs (`rg-...`) and offer IDs (`rgp-...`) are opaque strings. Always take them from the catalog; do not build or guess them. The `categoryId` and `offerId` values in the examples below are placeholders. ### `GET /catalog` Returns active categories. Optional query parameters: `q`, `limit` (1–100, default 50), and `offset`. ```bash curl 'https://gamesdrop.org/api/v1/catalog?limit=50' \ -H 'Authorization: Bearer GD_API_KEY' ``` Example response: ```json {"ok":true,"total":1,"categories":[{"id":"rg-XXXX","kind":"topup","title":"Free Fire — SG"}]} ``` ### `GET /catalog/{id}` Returns category details, required input fields, offers, and prices. `priceTjs` is your partner price. `retailPriceTjs` is the suggested retail price and may be `null`. Prices may change, so refresh them before placing an order. The `fields` list shows exactly which keys you must send in `fields` when you check an ID or create an order (for example `gameUserId`). A missing key returns `400 missing_field`. ```json {"ok":true,"category":{"id":"rg-XXXX","kind":"topup","title":"Free Fire — SG","fields":[{"key":"gameUserId","label":"Player ID","type":"text","options":null}],"idCheckField":"gameUserId","offers":[{"offerId":"rgp-XXXX","title":"110 Diamonds","priceTjs":"8.75","retailPriceTjs":null}],"steamTopup":null}} ``` `steamTopup` is `null` for ordinary categories. For a category that supports Steam top-up by amount it is an object: - `minUsd`, `maxUsd` — allowed amount range in USD - `tjsPerUsd` — your rate in TJS per 1 USD (already includes your price level) - `noFeeFromUsd`, `tjsPerUsdNoFee` — optional; a better rate for amounts from `noFeeFromUsd` ## 4. Player ID check ### `POST /check-id` Request (use the key from `idCheckField`): ```json {"categoryId":"rg-XXXX","fields":{"gameUserId":"123456789"}} ``` Example response: ```json {"ok":true,"valid":true,"playerName":"PlayerOne","region":"SG"} ``` `valid:true` means the ID is confirmed. `valid:false` means the ID was not confirmed: it is wrong, belongs to another region, or the game cannot be verified. `503 check_unavailable_now` means the check is temporarily unavailable; it does not mean the ID is invalid. ## 5. Create an order ### `POST /orders` Headers: ```http Authorization: Bearer GD_API_KEY Content-Type: application/json Idempotency-Key: NEW-UUID ``` Standard product: ```json {"categoryId":"rg-XXXX","offerId":"rgp-XXXX","fields":{"gameUserId":"123456789"}} ``` Steam top-up (only for categories where `steamTopup` is not `null`; otherwise `400 invalid_request`): ```json {"categoryId":"STEAM_CATEGORY_ID","amountUsd":20,"fields":{"login":"steamlogin"}} ``` `amountUsd` is a number (not a string), greater than 0, with at most 2 decimals, within `minUsd`–`maxUsd`. Do not send `offerId` together with `amountUsd`. In the response of a Steam order `offerId` is `null` and `amountUsd` is returned. The exact price is in `order.priceTjs`; it may differ from `amountUsd × tjsPerUsd` by up to 0.01 TJS because of rounding. Example response: ```json {"ok":true,"order":{"id":"UUID","number":128,"categoryId":"rg-XXXX","offerId":"rgp-XXXX","priceTjs":"8.75","status":"processing","delivery":null,"error":null,"createdAt":"2026-10-11T10:00:00Z","completedAt":null}} ``` The order price is deducted from the GamesDrop internal balance. If funds are insufficient, the API returns `402 insufficient_balance` and no order is created. Idempotency: repeating a request with the same `Idempotency-Key` and the same body returns the original order (or the original error) and never creates a second order. If the first request is still being processed you get `409 in_progress`; wait a few seconds and repeat. The same key with a different body returns `422 idempotency_key_reuse`. If the provider fails to fulfil the order, the API returns `502 fulfillment_failed` with the order in the `order` field. The funds are returned and the order status is `refunded`. ## 6. Retrieve orders - `GET /orders/{id}` — retrieve an order by UUID or short order number. - `GET /orders?status=processing&limit=50&offset=0` — list orders (newest first) with filtering and pagination. `limit` is 1–100 (default 50). The response contains `total` and `orders`. Statuses: `processing` (in progress), `fulfilled` (completed), `refunded` (the provider failed and the funds were returned), and `failed` (the order failed; see the `error` field). Do not rely on `processing` ending quickly: use webhooks or poll `GET /orders/{id}`. ## 7. Balance ### `GET /balance` ```json {"ok":true,"balanceTjs":"125.40"} ``` This is your GamesDrop account balance. All amounts are shown in Tajik somoni (TJS) with two decimal places. ## 8. Webhooks Configure a webhook in your account → **API**, or through the API. The URL must meet these rules: `https://` only, port 443 only, no login or password in the URL, and the host must resolve to a public IPv4 address (private, local, and IPv6-only hosts are rejected with `400 invalid_request`). Redirects are not followed. - `PUT /webhook` — save a URL: `{"url":"https://example.com/hook"}`. The response shows the full secret (`whsec_...`). - `GET /webhook` — retrieve settings (the secret is partly hidden), the time and result of the last delivery, and `failsInARow`. - `POST /webhook` — management actions. Rotate the secret with `{"action":"rotate_secret"}`; the response shows the new secret. - Disable it with `PUT /webhook` and `{"url":null}`. Events: `order.fulfilled`, `order.refunded`, and `order.failed`. Request body: ```json {"event":"order.fulfilled","sentAt":"2026-10-11T10:00:05Z","order":{"id":"UUID","number":128,"status":"fulfilled","...":"same fields as GET /orders/{id}"}} ``` Signature header: `X-GamesDrop-Signature: t=UNIX,v1=HEX`. The signature is HMAC-SHA256 of `t + "." + RAW_BODY` (the raw request body, byte for byte), using your webhook secret. Compare in constant time. Reject events whose `t` is older than five minutes. Delivery: your endpoint must answer with HTTP 2xx within 8 seconds. Otherwise GamesDrop retries: up to 4 attempts in total, with pauses of 1, 5, and 15 minutes. An HTTP 4xx answer is treated as final and is not retried. Every attempt is signed with a fresh `t`. Respond quickly and deduplicate repeated events using `order.id` and `event`. If something is missed, read the order with `GET /orders/{id}`. ## 9. Errors and rate limits Example error: ```json {"ok":false,"code":"insufficient_balance","error":"Дар ҳисоби панел маблағ нокифоя аст."} ``` The `error` text is for people and may change. Use `code`. Some errors have extra fields, for example `field` in `missing_field` and `retryAfterSeconds` in `rate_limited`. | HTTP | Code | Meaning | |---|---|---| | 400 | `invalid_request`, `missing_field` | Invalid request or missing field (`field` names it) | | 401 | `unauthorized`, `key_revoked` | Invalid or revoked API key | | 402 | `insufficient_balance` | Insufficient balance | | 403 | `account_blocked` | Account is blocked | | 404 | `not_found` | Category, offer, or order not found | | 405 | `method_not_allowed` | Method not allowed for this path | | 409 | `offer_unavailable`, `in_progress` | Offer unavailable or request still processing | | 422 | `idempotency_key_reuse` | An idempotency key was reused with a different payload | | 429 | `rate_limited` | Rate limit exceeded; retry later | | 500 | `internal_error` | Internal error; send `requestId` to support | | 502 | `fulfillment_failed` | Provider failed; funds are refunded; the response contains `order` | | 503 | `service_unavailable`, `check_unavailable_now` | Service temporarily unavailable | The default limit is 30 requests per minute per key (administrators can change it). On `429`, wait for `retryAfterSeconds` (also sent in the `Retry-After` header) before retrying. `429` can also mean the service is busy for all partners at the moment; the same rule applies. ## 10. Security 1. Never share your API Key or Webhook Secret or commit them to GitHub. 2. Use HTTPS only. 3. Make API requests from your server, not from a browser. 4. Use a new `Idempotency-Key` for each new order. 5. Verify the product price and player ID before ordering. 6. Verify the webhook signature on every event before you trust it.