iFragment

Заказы и статусы

Создание заказа, жизненный цикл, повторы и идемпотентность.

Order означает выдачу Stars или Premium одному получателю. Заказ принадлежит Project, который его создал.

Создание

POST
/v1/orders

Checks the recipient, holds the price on your balance and queues the Order (QUEUED). Repeating with the same externalId returns the existing Order (with different parameters: 409, code -9207). Stars: quantity 50 to 1,000,000; Premium: months 3, 6 or 12.

Authorization

apiKey
X-API-Key<token>

ifk_<clientId>_<secret>, for example ifk_48aa52d67c0fef6decb05b36_lVlZSWKN43sgb2vfEpFbqtzQ0ePNZya6yZr-RmJ4wxo

In: header

Header Parameters

Idempotency-Key*string

8 to 128 characters [A-Za-z0-9._:-], unique per operation

Match^[A-Za-z0-9._:-]{8,128}$

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/v1/orders" \  -H "Idempotency-Key: string" \  -H "Content-Type: application/json" \  -d '{    "externalId": "bot-order-1024",    "username": "durov",    "product": "STARS",    "quantity": 100  }'

{  "success": true,  "data": {    "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",    "externalId": "bot-order-1024",    "product": "STARS",    "quantity": 100,    "months": null,    "username": "durov",    "recipientName": "Pavel Durov",    "status": "QUEUED",    "price": "1.65",    "currency": "USD",    "failure": null,    "createdAt": "2026-10-06T09:15:22.443Z",    "sentAt": null,    "completedAt": null  },  "meta": {    "requestId": "9f1c2b7e-3a4d-4e5f-8a6b-7c8d9e0f1a2b",    "timestamp": "2026-10-06T09:15:22.481Z",    "processingTimeMs": 38  }}

POST /v1/orders
X-API-Key: ifk_…
Idempotency-Key: 5c0e1d7a-3b1f-4c1e-9d55-0f6b6a1b2c3d
Content-Type: application/json
{ "product": "STARS", "quantity": 500, "username": "durov", "externalId": "1042" }
ПолеТипОписание
productSTARS | PREMIUMчто выдать
quantityintegerдля STARS: от 50 до 1 000 000
months3 | 6 | 12для PREMIUM вместо quantity
usernamestringполучатель: durov, @durov или https://t.me/durov; от 4 до 32 символов [a-z0-9_], начинается с буквы
externalIdstringid заказа в вашей системе (от 1 до 128 символов), уникален в рамках Project

Ответ 201 содержит объект заказа:

{
  "id": "0199a1b2-6f00-7abc-9def-112233445566",
  "externalId": "1042",
  "product": "STARS",
  "quantity": 500,
  "months": null,
  "username": "durov",
  "recipientName": "Pavel Durov",
  "status": "QUEUED",
  "price": "8.25",
  "currency": "USD",
  "failure": null,
  "createdAt": "2026-09-26T10:15:30.000Z",
  "sentAt": null,
  "completedAt": null
}

price это строка в долларах США. failure заполнен только у FAILED: { "code": "RECIPIENT_NOT_FOUND", "message": "Telegram user not found" }.

При создании мы:

  1. проверяем получателя (через кэш): если его нет, сразу отвечаем 422 (-9002), если Premium нельзя подарить, отвечаем 422 (-9003); деньги при этом не блокируются;
  2. фиксируем цену по вашему прайсу, она сохраняется в заказе и дальше не меняется;
  3. блокируем сумму на балансе (HOLD), при нехватке отвечаем 402 (-9301);
  4. ставим заказ в очередь и отвечаем 201 со статусом QUEUED.

Статусы

GET
/v1/orders/{id}

Current state of one order: its status, what was bought and for how much. Poll it after creating an order, or subscribe to the webhook instead of polling.

Authorization

apiKey
X-API-Key<token>

ifk_<clientId>_<secret>, for example ifk_48aa52d67c0fef6decb05b36_lVlZSWKN43sgb2vfEpFbqtzQ0ePNZya6yZr-RmJ4wxo

In: header

Path Parameters

id*string
Formatuuid

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/v1/orders/497f6eca-6276-4993-bfeb-53cbbbba6f08"

{  "success": true,  "data": {    "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",    "externalId": "bot-order-1024",    "product": "STARS",    "quantity": 100,    "months": null,    "username": "durov",    "recipientName": "Pavel Durov",    "status": "SUCCEEDED",    "price": "1.65",    "currency": "USD",    "failure": null,    "createdAt": "2026-10-06T09:15:22.443Z",    "sentAt": "2026-10-06T09:15:31.902Z",    "completedAt": "2026-10-06T09:15:48.215Z"  },  "meta": {    "requestId": "9f1c2b7e-3a4d-4e5f-8a6b-7c8d9e0f1a2b",    "timestamp": "2026-10-06T09:15:22.481Z",    "processingTimeMs": 38  }}

GET
/v1/orders

Project orders, newest first.

Authorization

apiKey
X-API-Key<token>

ifk_<clientId>_<secret>, for example ifk_48aa52d67c0fef6decb05b36_lVlZSWKN43sgb2vfEpFbqtzQ0ePNZya6yZr-RmJ4wxo

In: header

Query Parameters

page?integer
Range1 <= value
Default1
limit?integer
Range1 <= value <= 100
Default20
status?string

QUEUED waiting, PROCESSING in progress, SENT transfer to the supplier sent and awaiting confirmation, SUCCEEDED delivered, FAILED not delivered (hold released), NEEDS_REVIEW an operator checks the outcome.

Value in

  • "QUEUED"
  • "PROCESSING"
  • "SENT"
  • "SUCCEEDED"
  • "FAILED"
  • "NEEDS_REVIEW"
externalId?string
Length1 <= length <= 128

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/v1/orders"
{  "success": true,  "data": [    {      "id": "2f1a8b3c-5d6e-4f70-8a9b-0c1d2e3f4a5b",      "externalId": "bot-order-1025",      "product": "PREMIUM",      "quantity": null,      "months": 6,      "username": "durov",      "recipientName": "Pavel Durov",      "status": "FAILED",      "price": "16.99",      "currency": "USD",      "failure": {        "code": "RECIPIENT_NOT_ELIGIBLE",        "message": "The recipient cannot receive this gift (Premium may already be active)"      },      "createdAt": "2026-10-06T09:16:02.118Z",      "sentAt": null,      "completedAt": "2026-10-06T09:16:05.774Z"    },    {      "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",      "externalId": "bot-order-1024",      "product": "STARS",      "quantity": 100,      "months": null,      "username": "durov",      "recipientName": "Pavel Durov",      "status": "SUCCEEDED",      "price": "1.65",      "currency": "USD",      "failure": null,      "createdAt": "2026-10-06T09:15:22.443Z",      "sentAt": "2026-10-06T09:15:31.902Z",      "completedAt": "2026-10-06T09:15:48.215Z"    }  ],  "meta": {    "requestId": "9f1c2b7e-3a4d-4e5f-8a6b-7c8d9e0f1a2b",    "timestamp": "2026-10-06T09:20:00.012Z",    "processingTimeMs": 21,    "pagination": {      "page": 1,      "limit": 20,      "totalItems": 2,      "totalPages": 1    }  }}
QUEUED ──▶ PROCESSING ──▶ SENT ──▶ SUCCEEDED
  ▲            │            │
  └── повтор ──┘            ├──▶ QUEUED        (доказано, что перевод не прошёл)
               │            └──▶ NEEDS_REVIEW ──▶ SUCCEEDED | FAILED
               └──▶ FAILED  (окончательная ошибка или 3 попытки)
СтатусЧто значитКонечный
QUEUEDв очереди, ждёт свободный Supplier Accountнет
PROCESSINGвыполняется: бронь у поставщика и отправка платежанет
SENTплатёж поставщику отправлен, ждём подтверждения в сетинет
SUCCEEDEDStars/Premium выданы, сумма списана (CAPTURE)да
FAILEDне выполнен, блокировка снята (RELEASE), деньги не списаныда
NEEDS_REVIEWисход неизвестен, заказ проверяет наша поддержка, итог придёт вебхукомнет

Обычно путь от QUEUED до SUCCEEDED занимает от 10 до 60 секунд. Если все аккаунты заняты (см. троттлинг), заказ ждёт в QUEUED, это нормально.

Повторы

Повторы делает платформа, вам не нужно пересоздавать заказ:

  • проблема аккаунта до отправки платежа (истекла сессия, мало средств на кошельке): заказ возвращается в QUEUED и берётся другим аккаунтом, попытка не тратится;
  • временная ошибка поставщика или сети до отправки: повтор через 30 секунд × номер попытки; всего 3 попытки, после них заказ получает FAILED с кодом ATTEMPTS_EXHAUSTED;
  • окончательная ошибка (получатель не найден, Premium уже активен): сразу FAILED с кодом RECIPIENT_NOT_FOUND или RECIPIENT_NOT_ELIGIBLE;
  • после SENT заказ повторяется, только если доказано, что перевод не исполнился (попытка тратится). Так двойная выдача и двойная оплата исключены; если исход не ясен за 10 минут, заказ уходит в NEEDS_REVIEW и решается вручную (при отказе заказ получает FAILED с кодом REJECTED_BY_REVIEW).
failure.codeПричина
RECIPIENT_NOT_FOUNDполучатель не найден у поставщика
RECIPIENT_NOT_ELIGIBLEполучателю нельзя подарить (например, Premium уже активен)
ATTEMPTS_EXHAUSTEDзаказ не удалось выполнить за 3 попытки
REJECTED_BY_REVIEWзаказ отменён после ручной проверки

Идемпотентность

Две защиты от дублей, используйте обе:

  • Idempotency-Key защищает конкретный HTTP-запрос. Повтор с тем же ключом и тем же телом вернёт тот же ответ (с заголовком Idempotent-Replayed: true), не создавая второй заказ. Тот же ключ с другим телом даёт 422 (-11002); если первый запрос ещё выполняется, ответ будет 409 (-11003), повторите чуть позже. Ответы с ошибкой не запоминаются: исправленный запрос можно повторить с тем же ключом. Генерируйте ключ один раз на операцию (например, UUID) и повторяйте его при таймауте.
  • externalId защищает заказ в вашей системе. Второй заказ с тем же externalId в Project не создастся, даже с новым Idempotency-Key: повторный POST с теми же параметрами вернёт уже созданный заказ, а с другими (username, product, quantity, months) вернёт 409 (-9207). Если вы не уверены, создан ли заказ, найдите его: GET /v1/orders?externalId=1042.

Получение

  • GET /v1/orders/{id}: один заказ; для заказа чужого Project ответ 404 (-9201).
  • GET /v1/orders?status=FAILED&externalId=1042&page=1&limit=20: список заказов Project, новые первыми (limit до 100); пагинация в meta.pagination.

На этой странице