GAMES DROP Logo

GamesDrop.io API - Руководство для мерчантов

[!WARNING] Все offer groups в этой документации являются PRODUCTION-офферами! Для тестирования используйте только Test Offer ID 999. API Base URL: https://partner.gamesdrop.io

Добро пожаловать в документацию Partner API GamesDrop.io! Это руководство содержит все необходимое для интеграции вашей реселлерской платформы с сетью GamesDrop.io. Интегрируясь с нами, вы получаете доступ к нашему каталогу из более чем 10 000 цифровых продуктов: от пополнения мобильных операторов до внутриигровой валюты популярных мобильных игр. Начните здесь, чтобы оптимизировать свои предложения продуктов и подключить своих клиентов к миру цифровых товаров.

Оглавление

  1. Авторизация
  2. Основные концепции
  3. Пошаговая интеграция
  4. API Endpoints
  5. Тестирование API
  6. Рекомендации по интеграции
  7. FAQ и Устранение неполадок
  8. Поддержка

Авторизация

Получение токена

Процесс получения

  1. Войдите в личный кабинет мерчанта
  2. Создайте новый магазин
  3. После создания магазина вы получите уникальный токен
  4. Формат токена: abcdef1234567890abcdef1234567890

Способы авторизации

Система поддерживает два способа авторизации в зависимости от типа запроса:

  1. API Токен магазина (Shop Token):

    • Используется для всех операций с товарами и заказами (создание заказа, проверка статуса, проверка баланса магазина).
    • Передается в заголовке: Authorization: <ваш_токен>
    • Пример: Authorization: abcdef1234567890abcdef1234567890
  2. JWT Токен (для управления):

    • Используется для личного кабинета и операций пополнения (Bank Transfer, PayPal и т.д.).
    • Передается как Bearer токен: Authorization: Bearer <jwt_token>
    • Примечание: JWT токен имеет ограниченный срок жизни.

Безопасность токена

  • 🔒 Токен является конфиденциальной информацией
  • ⚠️ Не передавайте токен третьим лицам
  • 📝 Токен нельзя восстановить после создания
  • 🔄 При необходимости можно сгенерировать новый токен (старый станет недействительным)

Основные концепции

Статусы заказов

СтатусОписаниеДействия
SUBMITTEDЗаказ создан и ожидает обработкиОжидать перехода в PROCESSING
PROCESSINGЗаказ в процессе обработкиОжидать завершения. Для прямых пополнений этот этап может занимать от 1 до 60 минут.
COMPLETEDЗаказ успешно выполненПолучить ключ/товар
CANCELEDЗаказ отменен без успешной доставкиПроверить данные заказа и создать новый заказ при необходимости
FAILEDОшибка провайдера или системыПрекратить опрос; создать новый заказ при необходимости
REFUNDЗаказ отменен, средства возвращены на баланс партнераСредства возвращены на баланс партнера

Поле message является необязательным и может отсутствовать в ответе. Для legacy-совместимости часть внутренних состояний FAILED в order-status может отображаться как CANCELED; при этом create-order может напрямую вернуть FAILED или REFUND.

Возможные ошибки

Код ошибкиОписаниеРешение
INVALID_TOKENНеверный токен авторизацииПроверить токен или получить новый
OFFER_NOT_FOUNDТовар не найден или нет доступаПроверить ID товара и права доступа
TRANSACTION_DUPLICATEДубликат транзакцииИспользовать новый transaction_id
WRONG_PRICEНеверная цена товараОбновить информацию о цене
ORDER_NOT_FOUNDЗаказ не найденПроверить ID заказа
ORDER_NOT_PROCESSINGЗаказ еще не в обработкеДождаться перехода в статус PROCESSING
ORDER_NOT_COMPLETEDЗаказ еще не завершенДождаться завершения заказа
ORDER_ALREADY_CANCELEDЗаказ уже отмененСоздать новый заказ
ORDER_ALREADY_REFUNDEDЗаказ уже возвращенСоздать новый заказ
SERVICE_UNAVAILABLEСервис временно недоступенПовторить попытку позже
INVALID_REQUEST_BODYНеверный формат запросаПроверить структуру запроса
INSUFFICIENT_BALANCEНедостаточно средств на балансеПополнить баланс или уменьшить сумму покупки
BALANCE_UNAVAILABLEБаланс временно недоступенПовторить запрос позже

Совместимость расчетов с поставщиками

GamesDrop работает с несколькими поставщиками. Некоторые поставщики работают через фиатные расчетные каналы, некоторые через USDT, а некоторые поддерживают оба варианта. Чтобы избежать валютных рисков, каждому партнерскому аккаунту назначается balance profile, а каждому офферу поставщика назначается settlement method.

Профили баланса:

ПрофильЗначение
FIATПартнер настроен на фиатные расчеты.
USDTПартнер настроен на расчеты в USDT.
MIXEDПартнер может использовать офферы поставщиков FIAT и USDT.

Методы расчетов офферов:

МетодЗначение
FIATОффер поставщика рассчитывается через фиатные каналы.
USDTОффер поставщика рассчитывается через USDT.
MIXEDОффер доступен как FIAT-, так и USDT-партнерам.

Правила совместимости:

Balance profile партнераВидимые / доступные к покупке методы офферов
FIATFIAT, MIXED
USDTUSDT, MIXED
MIXEDFIAT, USDT, MIXED

Catalog и product endpoints возвращают только совместимые офферы. Если оффер несовместим с профилем вашего аккаунта, он скрывается из sync и find-one, а создание заказа напрямую будет отклонено.

Этот слой совместимости не связан с наценкой на товар и конвертацией валют. GamesDrop возвращает финальную цену покупки, доступную вашему аккаунту; при создании заказа всегда используйте последнюю price, полученную из sync или find-one.

Пошаговая интеграция

Используйте вызовы в таком порядке для заведения каталога товаров и создания заказов:

  1. Загрузить каталог

    • POST /api/v1/offers/sync
    • Передайте необязательный ISO 3166-1 alpha-2 countryCode (например, US или DE), чтобы рассчитать совместимость со страной активации. Это не фильтрует глобальный каталог.
    • Используйте этот ответ, чтобы создать или обновить товары в вашей системе.
    • Сохраните rows[].offerGroupId как числовой GamesDrop offerId для всех следующих запросов.
    • Сохраните названия товаров, названия офферов, цену, валюту, наличие, платформу/регион и обязательные customer-поля.
  2. Построить страницу товара или checkout-форму

    • Покажите productName, offerGroupName, price и currency.
    • Если isRequiredGameUserId=true, запросите у клиента game/user/player ID.
    • Если isRequiredGameServerId=true, получите список серверов и попросите клиента выбрать сервер.
  3. Обновить выбранный оффер перед оплатой/созданием заказа

    • POST /api/v1/offers/find-one
    • Передайте числовой GamesDrop offer group ID и тот же необязательный countryCode.
    • Используйте возвращённую price как подтверждённую цену GamesDrop для create-order.
  4. Получить серверы, если нужны

    • Если isRequiredGameServerId=true, вызовите POST /api/v1/partner/product-offer/servers.
    • Покажите ключи ответа пользователю как названия, а выбранное значение отправляйте как gameServerId.
  5. Проверить данные игрока, если нужны

    • Если isRequiredGameUserId=true, вызовите POST /api/v1/offers/check-game-data.
    • Для игр, которым нужен сервер, передайте gameServerId.
  6. Создать заказ

    • POST /api/v1/offers/create-order
    • Передайте offerId, последнюю GamesDrop price, уникальный transactionId, тот же необязательный countryCode и обязательные customer-поля.
    • Для предоплатных заказов с баланса передавайте useBalance: true. Если вы не интегрируете баланс, используйте согласованный с GamesDrop settlement flow.
  7. Проверять статус заказа

    • POST /api/v1/offers/order-status
    • Используйте order_id, который вернул create-order, как orderId.
    • Опрос выполняется до финального статуса: COMPLETED, CANCELED, FAILED или REFUND.

Что сохранять из sync

ПолеКак использовать
offerGroupIdСохраните как GamesDrop offerId. Передавайте это значение в find-one, servers, check-game-data и create-order.
productNameНазвание товара в вашем каталоге.
offerGroupNameПродаваемый номинал/вариант, который видит клиент.
price + currencyЦена покупки GamesDrop для вашего аккаунта. Перед созданием заказа обновляйте через find-one.
inStockПоказывайте/продавайте только если true.
isRequiredGameUserIdЕсли true, checkout должен собрать customer.gameUserId.
isRequiredGameServerIdЕсли true, вызовите servers и соберите customer.gameServerId.
platformCode, platformName, regionCode, regionNameНеобязательные данные для отображения/фильтров. Используйте эти поля, а не парсинг региона/платформы из названия.
regionalLimitations, excludedCountryCodes, countryCompatibilityДанные для предупреждения об активации. Исключенная страна получает статус blocked, но API не отклоняет заказ. ROW не гарантирует активацию во всех странах.
selectedKeyFormat, availableKeyFormats, selectedKeyStockФормат выдачи (text или image), доступные форматы и физический остаток выбранного seller offer. Image-key доступен только магазинам с отдельным opt-in.

Правила параметров create-order

ПараметрКогда обязателенПримечание
offerIdВсегдаЧисловой GamesDrop offer group ID из sync.
priceВсегдаПоследняя цена GamesDrop из find-one или sync; не передавайте вашу розничную цену для клиента.
transactionIdВсегдаУникальный ID из вашей системы. Повторное использование вернёт существующий заказ или ошибку дубля.
countryCodeРекомендуется для игровых ключейISO 3166-1 alpha-2 код страны активации. Если у магазина настроена страна по умолчанию, она используется при отсутствии поля.
keyFormatТолько для image-keyПередайте image, только если find-one вернул selectedKeyFormat: "image". Старые запросы без поля остаются text-only.
useBalanceBalance/prepaid flowИспользуйте true для предоплатных заказов с баланса. Не передавайте для тестового offer 999 и settlement flows, согласованных отдельно.
customer.emailНеобязательноИспользуется для отслеживания/поддержки.
customer.gameUserIdЕсли isRequiredGameUserId=truePlayer ID, game account ID, Telegram user ID или другой идентификатор доставки.
customer.gameServerIdЕсли isRequiredGameServerId=trueИспользуйте значение, которое вернул servers, например os_euro.

Для key/gift-card товаров, где isReturnDataForCustomer=true и player-поля не нужны, обычно достаточно отправить offerId, price, transactionId и необязательный customer.email.

API Endpoints

Управление балансом

Проверка баланса

Вы можете проверить текущий баланс вашего аккаунта, используя API токен магазина.

HTTP
GET /api/v1/partner/balance
Authorization: {{token}}

[!NOTE] Эндпоинт /api/v1/balance требует JWT-авторизацию и используется в основном для веб-интерфейса. Для интеграции по Shop Token используйте /api/v1/partner/balance.

Response:

JSON
{
  "balance": 500.25,
  "draft_balance": 0.00,
  "is_postpaid": false,
  "balance_profile": "USDT",
  "currency": {
    "id": 3,
    "code": "USD"
  },
  "partner_id": 123,
  "shop_id": 70,
  "shop_name": "EasyPay",
  "owner_id": 392
}

Описание полей ответа:

КлючЗначениеДополнение
balancenumberТекущий доступный баланс
draft_balancenumberЗарезервированные средства (в обработке)
is_postpaidbooleantrue: аккаунт с постоплатой. false: предоплатный аккаунт.
balance_profileFIAT | USDT | MIXEDОпределяет, какие settlement methods офферов поставщиков видны и доступны к покупке.
partner_idnumberУникальный ID партнерского аккаунта
shop_idnumberID магазина, определённый по токену
shop_namestringНазвание магазина, определённое по токену
owner_idnumberID пользователя-владельца магазина
currencyobjectИнформация о валюте баланса

История транзакций баланса

HTTP
GET /api/v1/balance/transactions?page=1&limit=20
Authorization: {{passwordHash}}

[!NOTE] Это endpoint личного кабинета/JWT, а не базового Shop Token order flow. Используйте его только при интеграции dashboard-level управления аккаунтом.

Response:

JSON
{
  "transactions": [
    {
      "id": 12,
      "amount": -75.00,
      "type": "PURCHASE",
      "description": "API Purchase - Virtual credits",
      "balanceAfter": 425.00,
      "createdAt": "2025-07-28T05:21:46.121Z"
    },
    {
      "id": 11,
      "amount": -50.00,
      "type": "PURCHASE",
      "description": "Test Purchase - Mobile game credits",
      "balanceAfter": 500.00,
      "createdAt": "2025-07-28T05:16:23.718Z"
    }
  ],
  "total": 25
}

Описание полей запроса:

КлючЗначениеДополнение
pagenumberНомер страницы (по умолчанию: 1)
limitnumberКоличество записей на странице (по умолчанию: 20)

Описание полей ответа:

КлючЗначениеДополнение
transactionsarrayСписок транзакций
transactions[].idnumberУникальный ID транзакции
transactions[].amountnumberСумма операции (отрицательная для списаний)
transactions[].typestringТип операции (DEPOSIT, PURCHASE, REFUND)
transactions[].descriptionstringОписание операции
transactions[].balanceAfternumberБаланс после операции
transactions[].createdAtstringДата и время операции (UTC)
totalnumberОбщее количество транзакций

Получение информации о товаре

HTTP
POST /api/v1/offers/find-one
Authorization: {{token}}

{
  "offerId": 1001,
  "offerGroupId": 1001,
  "productOfferId": 77881,
  "providerProductId": "620b94639e44a1f3767893cc",
  "providerOfferId": "66e170989a659600013da9f3",
  "countryCode": "DE"
}

offerId в этом запросе должен быть числовым GamesDrop offer group ID, который возвращается как rows[].offerGroupId в sync. Не передавайте внешние ID провайдера или строковые коды продуктов.

Response:

JSON
{
  "offerId": 1001,
  "productName": "Total War: WARHAMMER III PC Steam CD Key",
  "offerName": "Total War: WARHAMMER III PC Steam CD Key",
  "platformCode": "steam",
  "platformName": "Steam",
  "regionCode": "ROW",
  "regionName": "RoW",
  "regionalLimitations": "Rest of the world (RoW) - custom",
  "excludedCountryCodes": ["KP", "JP", "CN", "HK", "KR", "TW"],
  "countryCompatibility": "allowed",
  "count": 1,
  "available": 4,
  "sellerOfferCount": 4,
  "selectedTextStock": 39,
  "price": 10.57,
  "currency": "USD",
  "priceBreakdown": {
    "providerPrice": 8.99,
    "providerCurrency": "EUR",
    "addedPercent": 3,
    "fxRate": 1.1418132,
    "price": 10.57,
    "currency": "USD"
  },
  "quoteCheckedAt": "2026-07-16T12:00:00Z",
  "quoteExpiresAt": "2026-07-16T12:00:45Z",
  "isPriceFresh": true,
  "settlementMethod": "MIXED",
  "balanceProfile": "MIXED",
  "isSettlementCompatible": true,
  "isReturnDataForCustomer": true,
  "isRequiredGameUserId": false,
  "isRequiredGameServerId": false
}

Описание полей запроса:

КлючЗначениеДополнение
offerIdnumberЧисловой GamesDrop offer group ID из sync; должно быть числом, не строкой
countryCodestringНеобязательный ISO 3166-1 alpha-2 код страны активации.

Описание полей ответа:

КлючЗначениеДополнение
offerId, offerGroupIdnumberСтабильный GamesDrop offer group ID. Оба поля всегда равны.
productOfferIdnumberВнутренний ID seller offer для диагностики. Не передавайте его как offerId.
providerProductId, providerOfferIdstringТочные ID провайдера для диагностики. Не передавайте их как offerId.
productNamestring-
offerNamestring-
platformCodestringНормализованный код платформы, если доступен.
platformNamestringНазвание платформы для отображения, если доступно.
regionCodestringНормализованный код региона, например GLB, EU, ROW, CIS, US, NA, EMEA, OTH.
regionNamestringНазвание региона для отображения, если доступно, например Global, Europe, RoW, CIS.
regionalLimitationsstringОбщая региональная метка поставщика.
excludedCountryCodesstring[]ISO-коды стран, где активация запрещена. Исключения имеют приоритет над общей меткой региона.
countryCompatibilityallowed | blocked | unverified | not_checkedРезультат проверки запрошенной страны или страны магазина по умолчанию.
countnumberКоличество единиц в запросе заказа, сейчас 1.
available, sellerOfferCountnumberЧисло доступных seller offers, а не количество ключей.
selectedTextStocknumberКоличество текстовых ключей выбранного exact seller offer.
selectedKeyFormattext | imageФактический формат выбранного seller offer.
availableKeyFormatsstring[]Форматы, разрешенные и доступные для вашего магазина.
selectedKeyStocknumberФизический остаток выбранного exact seller offer. Для image-key selectedTextStock равен 0.
pricenumber-
currencyKZT, USD, RUB, etc.Код валюты цены
priceBreakdownobjectЦена и валюта провайдера, партнерская наценка, FX и итоговая цена. MIXED не добавляет скрытую комиссию.
quoteCheckedAt, quoteExpiresAt, isPriceFreshstring, string, booleanСвежесть provider quote. Вызывайте find-one непосредственно перед заказом.
settlementMethodFIAT | USDT | MIXEDМетод расчетов выбранного оффера поставщика.
balanceProfileFIAT | USDT | MIXEDВаш профиль баланса партнера.
isSettlementCompatiblebooleanВсегда true для возвращаемых офферов. Несовместимые офферы скрываются.
isReturnDataForCustomerbooleantrue: Ключ/Карта (вернет key). false: Прямое пополнение (на баланс).
isRequiredGameUserIdbooleantrue, если для создания заказа нужен customer.gameUserId.
isRequiredGameServerIdbooleantrue, если для создания заказа нужен customer.gameServerId.

При создании заказа используйте offerGroupId из sync или тот же offerId из find-one. offerId и offerGroupId всегда равны стабильному ID группы GamesDrop. Не заменяйте их на productOfferId или provider ID.

Синхронизация каталога (B2B Sync)

Endpoint Sync предназначен для партнеров, которым нужно регулярно обновлять локальные базы товаров. Он возвращает плоский оптимизированный список доступных офферов, актуальные цены с учетом вашей наценки и наличие на складе в одном запросе.

Ответ включает только офферы, совместимые с вашим balanceProfile. Например, партнер с профилем USDT не получит в этой выдаче fiat-only офферы поставщиков.

Для отображения платформы и региона используйте поля platformCode/platformName и regionCode/regionName из ответа. Не считайте товар Global только по названию. ROW означает широкую зону Rest of World, но активация может быть недоступна для стран из excludedCountryCodes. Передавайте countryCode, чтобы получить статус предупреждения; товар при этом остается в глобальном каталоге.

HTTP
POST /api/v1/offers/sync
Authorization: {{token}}

{
  "limit": 1000,
  "page": 1,
  "category": "Top Up",
  "search": "genshin",
  "countryCode": "DE"
}

Описание полей запроса:

КлючЗначениеДополнение
limitnumberКоличество элементов на странице (максимум 5000). По умолчанию: 1000.
pagenumberНомер страницы. По умолчанию: 1.
searchstringНеобязательный текстовый поиск по названию товара.
categorystringНеобязательный фильтр по категории, например Top Up, Gift Cards. Также поддерживаются legacy aliases TOP_UP и GIFT_CARD.
countryCodestringНеобязательный ISO 3166-1 alpha-2 код страны активации. Рассчитывает countryCompatibility, но не исключает строки из глобального каталога.

Response:

JSON
{
  "count": 1250,
  "rows": [
    {
      "productId": 5,
      "productName": "PUBG Mobile",
      "offerGroupId": 101,
      "offerGroupName": "60 UC",
      "platformCode": "mobile",
      "platformName": "Mobile",
      "regionCode": "GLB",
      "regionName": "Global",
      "regionalLimitations": "REGION FREE",
      "excludedCountryCodes": [],
      "countryCompatibility": "allowed",
      "productOfferId": 77881,
      "providerProductId": "620b94639e44a1f3767893cc",
      "providerOfferId": "66e170989a659600013da9f3",
      "sellerOfferCount": 4,
      "selectedTextStock": 39,
      "price": 0.99,
      "currency": "USD",
      "isPriceFresh": true,
      "inStock": true,
      "isRequiredGameUserId": true,
      "isRequiredGameServerId": false
    }
  ]
}

Описание полей ответа:

КлючЗначениеДополнение
countnumberОбщее количество элементов, подходящих под фильтры.
rows[].offerGroupIdnumberID, который нужно передавать как offerId при создании заказа.
rows[].productOfferId, rows[].providerProductId, rows[].providerOfferIdnumber, string, stringДиагностические ID seller/provider. Не используйте их как offerId.
rows[].productNamestringНазвание продукта.
rows[].offerGroupNamestringНазвание продаваемого варианта.
rows[].platformCodestringНормализованный код платформы, если доступен.
rows[].platformNamestringНазвание платформы для отображения, если доступно.
rows[].regionCodestringНормализованный код региона, если доступен, например GLB, EU, ROW, CIS, US, NA. Не считайте товар Global только потому, что в названии написано PC Steam CD Key.
rows[].regionNamestringНазвание региона для отображения, если доступно, например Global, Europe, RoW, CIS, North America.
rows[].regionalLimitationsstringОбщая региональная метка поставщика.
rows[].excludedCountryCodesstring[]ISO-коды стран, где активация запрещена.
rows[].countryCompatibilityallowed | blocked | unverified | not_checkedСтатус предупреждения для запрошенной страны или страны магазина по умолчанию. Покупку не блокирует.
rows[].pricenumberФинальная стоимость покупки товара в вашей валюте.
rows[].priceBreakdownobjectЦена провайдера, партнерская наценка, FX и итоговая цена.
rows[].sellerOfferCountnumberЧисло eligible seller offers, не количество ключей.
rows[].selectedTextStocknumberПодтвержденный text stock выбранного offer.
rows[].quoteCheckedAt, rows[].quoteExpiresAt, rows[].isPriceFreshразныеСвежесть snapshot. sync может устареть; перед заказом окончательным источником является find-one.
rows[].inStockbooleantrue, если хотя бы один поставщик сейчас активен.
rows[].isRequiredGameUserIdbooleantrue, если товар требует идентификатор игрока.
rows[].isRequiredGameServerIdbooleantrue, если товар требует идентификатор сервера.

Создание заказа

HTTP
POST /api/v1/offers/create-order
Authorization: {{token}}

{
  "offerId": 1001,
  "price": 560.10,
  "transactionId": "test112321124214",
  "countryCode": "DE",
  "keyFormat": "text",
  "useBalance": true,
  "customer": {
    "email": "user@gmail.com",
    "gameUserId": "52357322414"
  }
}

Описание полей запроса:

КлючЗначениеДополнение
offerIdnumberЧисловой GamesDrop offer group ID из sync; должно быть числом, не строкой
pricenumberПоследняя цена покупки GamesDrop, полученная из find-one или sync. Не передавайте вашу розничную цену для клиента.
transactionIdstringУникальный идентификатор транзакции в вашей системе
countryCodestringНеобязательный ISO 3166-1 alpha-2 код страны активации. Используйте то же значение, что в sync и find-one.
keyFormattext | imageНеобязательно. Без поля API использует text-only. image разрешен только для магазинов с opt-in.
useBalancebooleanИспользуйте true для предоплатных заказов с баланса. Для тестового offer 999 можно не передавать.
customerobjectДанные клиента и доставки
customer.emailstringНеобязательное поле для отслеживания
customer.gameUserIdstringОбязательно, если isRequiredGameUserId=true
customer.gameServerIdstringОбязательно, если isRequiredGameServerId=true

Подтверждение цены и выбор поставщика

Поле price в create-order является подтверждением цены. Оно должно совпадать с ценой GamesDrop, которую ваша система получила из find-one или sync перед созданием заказа.

Не передавайте цену, которую видит ваш конечный клиент. Наценка вашего магазина управляется на вашей стороне и не является частью запроса заказа в GamesDrop.

Для товаров с несколькими поставщиками GamesDrop может выбрать лучшего доступного поставщика в момент создания заказа. Заказ будет принят только если подтвержденная price все еще покрывает требуемую цену покупки GamesDrop. Если цены поставщиков изменились или самый дешевый поставщик стал недоступен, API вернет WRONG_PRICE, OFFER_NOT_FOUND, OUT_OF_STOCK или SERVICE_UNAVAILABLE в зависимости от ситуации. В этом случае обновите цену оффера и попросите клиента повторить покупку.

Response:

JSON
{
  "order_id": 10222502,
  "count": 1,
  "price": 560.10,
  "currency": "RUB",
  "offer_id": 1001,
  "product_name": "PUBG MOBILE GIFT",
  "offer_name": "60 UC",
  "status": "COMPLETED",
  "is_return_data_for_customer": true,
  "selected_key_format": "text",
  "key": "001434249936"
}

Описание полей ответа:

КлючЗначениеДополнение
order_idnumber-
countnumberКоличество единиц товара
pricenumber-
currencyKZT | USD | EUR | RUB-
offer_idnumberGamesDrop offer group ID, использованный для заказа
product_namestring-
offer_namestring-
statusstringSUBMITTED, PROCESSING, COMPLETED, CANCELED, FAILED, REFUND
is_return_data_for_customerbooleantrue: Товар-ключ. false: Прямое пополнение.
keystring (optional)Код активации/PIN. Присутствует ТОЛЬКО если is_return_data_for_customer: true И статус COMPLETED.
selected_key_formattext | imageФормат фактической выдачи.
fulfillment_itemsobject[] (optional)Для image-key содержит format, mimeType, fileName, contentBase64 и provider IDs. Возвращается авторизованному магазину только после COMPLETED; base64 не дублируется в key.

Для selected_key_format: "image" декодируйте fulfillment_items[].contentBase64 согласно mimeType и передайте клиенту оригинальное изображение без изменения. Не применяйте OCR как источник истины и не записывайте base64/serial в логи.

[!NOTE] create-order сейчас возвращает поля в snake_case. order-status возвращает поля в camelCase для legacy-совместимости.

Проверка статуса заказа

HTTP
POST /api/v1/offers/order-status
Authorization: {{token}}

{
  "orderId": 10222502
}

Описание полей запроса:

КлючЗначениеДополнение
orderIdnumberGamesDrop order ID, который create-order вернул как order_id

[!NOTE] Короткий endpoint /api/v1/offers/order-status сейчас проверяет заказ по orderId. Если нужен поиск по transactionId, используйте legacy endpoint POST /api/v1/partner/product-offer/status.

Response:

JSON
{
  "orderId": 10222502,
  "count": 1,
  "price": 560.10,
  "currency": "RUB",
  "offerId": 1001,
  "productName": "PUBG MOBILE GIFT",
  "offerName": "60 UC",
  "status": "COMPLETED",
  "isReturnDataForCustomer": true,
  "key": "001434249936",
  "createdAt": "2024-05-28 10:08:04.296+00"
}

Описание полей ответа:

КлючЗначениеДополнение
orderIdnumber-
countnumberКоличество единиц товара
pricenumber-
currencyKZT | USD | EUR | RUB-
offerIdnumberGamesDrop offer group ID
productNamestring-
offerNamestring-
statusstringТекущий статус: SUBMITTED, PROCESSING, COMPLETED, CANCELED, FAILED, REFUND
messagestring (optional)Дополнительные детали статуса, если доступны; поле не гарантировано.
isReturnDataForCustomerbooleantrue: Товар-ключ. false: Прямое пополнение.
keystring (optional)Код активации/PIN. Присутствует ТОЛЬКО если isReturnDataForCustomer: true И статус COMPLETED.
createdAtstringUTC +0

[!NOTE] Для legacy-совместимости часть внутренних состояний FAILED может возвращаться из order-status как CANCELED. Оба статуса нужно считать финальными неуспешными статусами.

Получение списка серверов

Для товаров, которым требуется идентификатор сервера (isRequiredGameServerId: true), вы можете получить список доступных серверов и показать его в вашем UI.

HTTP
POST /api/v1/partner/product-offer/servers
Authorization: {{token}}

{
  "offerId": 1001
}

Response:

JSON
{
  "Europe": "os_euro",
  "America": "os_usa",
  "Asia": "os_asia"
}

Примечание: используйте ключ, например "Europe", как label для отображения, а значение, например "os_euro", как gameServerId при создании заказа.

Проверка игрока

HTTP
POST /api/v1/offers/check-game-data
Authorization: {{token}}

{
  "offerId": 1001,
  "gameUserId": "52357322414",
  "gameServerId": "1234"
}

Описание полей запроса:

КлючЗначениеДополнение
offerIdnumberВажно: должно быть числом, не строкой
gameUserIdstringИдентификатор игрока
gameServerIdundefined | stringИдентификатор сервера (если требуется)

Успешный ответ:

JSON
{
  "status": "VALID",
  "gameUserLogin": "JJJ"
}

Описание полей успешного ответа:

КлючЗначениеДополнение
status"VALID"Игрок валиден
gameUserLoginstringЛогин игрока

Ответ при ошибке:

JSON
{
  "status": "INVALID"
}

Описание полей ответа с ошибкой:

КлючЗначениеДополнение
status"INVALID"Игрок не валиден

Тестирование API

Тестовый товар

Для тестирования интеграции с API доступен специальный тестовый товар:

  • ID товара: 999
  • Название: Steam US
  • Наименование: TEST OFFER GROUP
  • Цена: используйте значение, которое вернул find-one
  • Возвращает ключ: Да

Пример запроса информации о тестовом товаре:

HTTP
POST /api/v1/offers/find-one
Authorization: {{token}}

{
  "offerId": 999
}

Пример создания тестового заказа:

HTTP
POST /api/v1/offers/create-order
Authorization: {{token}}

{
  "offerId": 999,
  "price": 21.79,
  "transactionId": "test_123456",
  "customer": {
    "email": "test@example.com",
    "gameUserId": "123456789"
  }
}

Перед созданием тестового заказа вызовите find-one для offerId: 999 и скопируйте возвращённую price в create-order. Не хардкодьте цену из примера: она может отличаться в зависимости от валюты магазина и настроек цены.

Особенности тестового товара:

  • Возвращает выполненный тестовый заказ, если тестовый оффер включён для вашего магазина
  • Генерирует тестовый ключ активации
  • Создаёт заказ со статусом COMPLETED
  • Проверка игрока всегда возвращает VALID для тестового товара
  • Работает в тестовом режиме без заказа у провайдера

Примеры работы с балансом

Проверка баланса перед покупкой:

JAVASCRIPT
// 1. Проверяем текущий баланс
const balanceResponse = await fetch('/api/v1/partner/balance', {
  headers: { 'Authorization': 'your-token-here' }
});
const { balance } = await balanceResponse.json();

// 2. Получаем информацию о товаре
const offerResponse = await fetch('/api/v1/offers/find-one', {
  method: 'POST',
  headers: {
    'Authorization': 'your-token-here',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ offerId: 1001 })
});
const { price } = await offerResponse.json();

// 3. Проверяем достаточность средств
if (balance >= price) {
  // Создаем заказ
  console.log('Sufficient balance, creating order...');
} else {
  console.log('Insufficient balance, need to top up');
}

Получение истории транзакций:

JAVASCRIPT
const transactionsResponse = await fetch('/api/v1/balance/transactions', {
  headers: { 'Authorization': 'Bearer your-dashboard-jwt-token' }
});
const { transactions, total } = await transactionsResponse.json();

console.log(`Total transactions: ${total}`);
transactions.forEach(tx => {
  console.log(`${tx.createdAt}: ${tx.type} ${tx.amount} (Balance: ${tx.balanceAfter})`);
});

Рекомендации по использованию

💰 Работа с балансом

  • Регулярно проверяйте баланс перед крупными покупками
  • Ведите учет транзакций для сверки с вашей системой
  • При недостатке средств уведомляйте пользователей о необходимости пополнения
  • Используйте пагинацию при запросе истории транзакций

🔍 Перед созданием заказа

  • Получите актуальную информацию о товаре
  • Проверьте достаточность баланса для покупки
  • Проверьте валидность игрока (в случае прямого пополнения)

📝 При создании заказа

  • Используйте уникальный transactionId
  • Указывайте последнюю цену GamesDrop, полученную из find-one или sync
  • Не передавайте вашу розничную цену для клиента в поле price
  • Указывайте offerId как число, не как строку
  • Заполняйте все необходимые поля для данного типа товара

✅ После создания заказа

  • Сохраните orderId
  • Проверяйте статус заказа
  • При статусе COMPLETED получите ключ/товар

⚠️ При возникновении ошибок

  • Проверьте токен
  • Убедитесь в корректности данных и формате запроса
  • Создайте новый заказ при необходимости

FAQ и Устранение неполадок

Типы товаров (Пополнение vs Ключи)

Наша система поддерживает два основных типа доставки. Вы можете различить их, используя поле isReturnDataForCustomer в ответе информации о товаре.

1. Подарочные карты / Ключи (isReturnDataForCustomer: true)

  • Что это: Клиент получает цифровой код, PIN или ссылку для ручной активации.
  • Поток:
    1. create-order возвращает status: "COMPLETED" и поле key.
    2. Вы показываете этот key своему клиенту.
  • Пример: Код пополнения Steam (Wallet Code), код на UC в PUBG.

2. Прямое пополнение (isReturnDataForCustomer: false)

  • Что это: Средства зачисляются напрямую на игровой аккаунт игрока. Код не возвращается.
  • Поток:
    1. Вы ОБЯЗАНЫ передать gameUserId (и иногда gameServerId) в запросе create-order.
    2. Мы рекомендуем сначала проверить валидность ID через /check-game-data.
    3. create-order возвращает текущий статус. Опросите order-status, пока заказ не станет COMPLETED или CANCELED.
  • Пример: Пополнение Mobile Legends Diamonds по User ID.

Конвертация валют

  • Ваш баланс партнера: Всегда ведется в USD.
  • Цены товаров: Могут быть в разных валютах (RUB, KZT, EUR и т.д.) в зависимости от региона.
  • Как это работает:
    • Вам не нужно конвертировать средства вручную.
    • Когда вы покупаете товар с ценой в RUB (например, 500 RUB), система рассчитывает эквивалент в USD (например, $5.50) и списывает его с вашего USD баланса.
    • Убедитесь, что у вас достаточно баланса в USD для покрытия конвертированной суммы.
  • Совместимость расчетов с поставщиками: ваш каталог фильтруется по balanceProfile до возврата цен. Это предотвращает продажу fiat-only офферов USDT-only партнерам и наоборот.
  • Без ручной FX-наценки: GamesDrop не требует добавлять дополнительный процент на потери конвертации в API-запрос. Используйте последнюю цену, возвращенную find-one или sync. Любая настроенная B2B-наценка уже включена в возвращаемую цену покупки GamesDrop.

Частые вопросы

"Я вижу упоминание параметра 'it', что это?"

В нашем API нет параметра с именем it. Вероятно, это опечатка вместо id или недопонимание.

  • Идентификатор товара: offerId.
  • Идентификатор транзакции: transactionId.
  • Идентификатор пользователя: gameUserId.

"Как проверить валидность ID игрока?"

Используйте эндпоинт POST /api/v1/offers/check-game-data. Он вернет VALID и никнейм игрока, если ID верен. Это настоятельно рекомендуется для товаров с прямым пополнением, чтобы избежать ошибок.

Поддержка

При возникновении вопросов обращайтесь в техническую поддержку:

Рекомендации по обработке ошибок

🔍 Проверка перед запросом

  • Валидация токена
  • Проверка ID товара
  • Актуальность цены
  • Уникальность transaction_id
  • Корректность формата данных (особенно offerId как число)

🛠 Обработка ответов

  • Обработка всех кодов ошибок
  • Логирование ошибок
  • Механизм повторных попыток

📊 Работа с заказами

  • Сохранение ID заказов
  • Мониторинг статусов
  • Актуализация данных

Telegram Stars

🌟 GamesDrop интегрировал поддержку Telegram Stars! Теперь вы можете отправлять Telegram Stars пользователям через те же стандартные API эндпоинты.

Доступные продукты Telegram Stars

Для Partner API offerId должен быть числовым GamesDrop offer group ID, который возвращается sync или find-one. Строковые ID ниже являются внутренними идентификаторами продуктов провайдера и приведены только для справки.

Internal Provider Product IDКоличество StarsДинамическая цена
telegram_stars_5050Основана на курсе TON
telegram_stars_100100Основана на курсе TON
telegram_stars_500500Основана на курсе TON
telegram_stars_10001000Основана на курсе TON

Как работает ценообразование:

  • A6-Gateway получает актуальный TON/USD курс от kernel currency API
  • Цена рассчитывается на основе Fragment.com коэффициентов (100 Stars ≈ 0.3 TON)
  • Цены обновляются в реальном времени при каждом запросе

Использование тех же эндпоинтов

1. Получение информации о Telegram Stars:

HTTP
POST /api/v1/offers/find-one
Authorization: {{token}}

{
  "offerId": 1001
}

Response:

JSON
{
  "offerId": 1001,
  "productName": "Telegram Stars",
  "offerName": "100 Stars",
  "count": 1,
  "price": 0.77,
  "currency": "USD",
  "isReturnDataForCustomer": true
}

2. Создание заказа на Telegram Stars:

HTTP
POST /api/v1/offers/create-order
Authorization: {{token}}

{
  "offerId": 1001,
  "price": 0.77,
  "transactionId": "tg_stars_12345",
  "customer": {
    "email": "user@example.com",
    "gameUserId": "143594291"
  }
}

Ответ create-order:

JSON
{
  "order_id": 10228901,
  "count": 1,
  "price": 0.78,
  "currency": "USD",
  "offer_id": 1001,
  "product_name": "Telegram Stars",
  "offer_name": "100 Stars",
  "status": "SUBMITTED",
  "is_return_data_for_customer": false
}

Для проверки финальной доставки используйте order-status:

JSON
{
  "orderId": 10228902,
  "transactionId": "tg_stars_12345",
  "count": 1,
  "price": 0.78,
  "currency": "USD",
  "offerId": 1001,
  "productName": "Telegram Stars",
  "offerName": "100 Stars",
  "status": "CANCELED",
  "isReturnDataForCustomer": false,
  "createdAt": "2025-08-26T12:30:15.234Z"
}

🔑 Важные особенности Telegram Stars

gameUserId требования:

  • gameUserId должен быть числовой Telegram User ID для создания заказа
  • Получить User ID можно двумя способами:
    1. 📞 Через @userinfobot в Telegram
    2. 🆕 Через наш API валидации (см. раздел ниже)
  • Пример: "gameUserId": "143594291"
  • ❌ НЕ username (@username) для создания заказа

Статусы доставки:

  • COMPLETED - Stars успешно доставлены пользователю
  • CANCELED - Не удалось доставить (неверный user ID, заблокирован бот, etc.)

Типичные ошибки доставки:

  • "user not found" - неверный Telegram User ID
  • "STARGIFT_INVALID" - пользователь не может получить Stars (restrictions)
  • "bot was blocked by user" - пользователь заблокировал бота

🆔 Валидация Telegram пользователей

🎯 Новый endpoint для валидации username и получения User ID!

Если ваши пользователи знают только свой @username, используйте этот endpoint для получения User ID перед созданием заказа.

Endpoint валидации:

HTTP
POST https://gamesdrop.io/api/aggregator/a6/telegram/user-info
Authorization: {{token}}
Content-Type: application/json

{
  "username": "@igoryan34"
}

Response при успешной валидации:

JSON
{
  "valid": true,
  "username": "igoryan34",
  "userInfo": {
    "id": 143594291,
    "first_name": "Igor",
    "username": "igoryan34",
    "photo_url": "AQADAgADRKgxGzMTjwgABCAI..."
  },
  "message": "User account verified successfully"
}

Response при невозможности получить User ID:

JSON
{
  "valid": true,
  "username": "igoryan34",
  "userInfo": {
    "username": "igoryan34",
    "first_name": "igoryan34"
  },
  "message": "Username format is valid, but user details are not publicly available. Full verification requires user interaction with the bot."
}

Описание полей запроса:

КлючЗначениеДополнение
usernamestringTelegram username с @ или без

Описание полей ответа:

КлючЗначениеДополнение
validbooleanВсегда true для корректных username
usernamestringОчищенный username без @
userInfo.idnumber🎯 User ID для заказов (если доступен)
userInfo.first_namestringИмя пользователя
userInfo.usernamestringUsername пользователя
userInfo.photo_urlstringURL аватара (если доступен)
messagestringОписание результата валидации

⚠️ Важные особенности:

  • Endpoint возвращает User ID только если пользователь взаимодействовал с ботом
  • Если userInfo.id отсутствует, попросите пользователя написать боту @gamesdrop_api_bot
  • Можно передавать как "@username", так и "username"
  • Можно также передавать User ID для получения дополнительной информации

📱 Интеграция для разработчиков

Пример полного flow на JavaScript с валидацией username:

JAVASCRIPT
// 1. Валидировать username и получить User ID
const validateTelegramUser = async (username) => {
  const response = await fetch('https://gamesdrop.io/api/aggregator/a6/telegram/user-info', {
    method: 'POST',
    headers: {
      'Authorization': 'your-token-here',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ username })
  });

  const result = await response.json();

  if (result.valid && result.userInfo && result.userInfo.id) {
    return {
      userId: result.userInfo.id,
      firstName: result.userInfo.first_name,
      username: result.userInfo.username
    };
  } else {
    throw new Error('Unable to get User ID. Please ask user to message @gamesdrop_api_bot first.');
  }
};

// 2. Найти числовой offer group ID в синхронизированном каталоге
const getTelegramStarsOfferGroupId = async (starsAmount) => {
  const response = await fetch('/api/v1/offers/sync', {
    method: 'POST',
    headers: {
      'Authorization': 'your-token-here',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ limit: 5000, page: 1, search: 'Telegram Stars' })
  });
  const catalog = await response.json();
  const row = catalog.rows.find((item) =>
    item.productName?.includes('Telegram Stars') &&
    item.offerGroupName?.includes(String(starsAmount))
  );
  if (!row) {
    throw new Error(`Telegram Stars offer group not found for ${starsAmount} Stars`);
  }
  return row.offerGroupId;
};

// 3. Получить актуальную цену
const getStarsPrice = async (starsAmount) => {
  const offerGroupId = await getTelegramStarsOfferGroupId(starsAmount); // Получаем из синхронизированного каталога
  const response = await fetch('/api/v1/offers/find-one', {
    method: 'POST',
    headers: {
      'Authorization': 'your-token-here',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      offerId: offerGroupId
    })
  });
  return response.json();
};

// 4. Отправить Stars пользователю
const sendStarsByUsername = async (usernameOrId, starsAmount) => {
  // Сначала получаем User ID если передали username
  let userId;
  if (isNaN(usernameOrId)) {
    // Это username, нужно получить User ID
    const userInfo = await validateTelegramUser(usernameOrId);
    userId = userInfo.userId;
    console.log(`✅ Validated user: ${userInfo.firstName} (@${userInfo.username}) - ID: ${userId}`);
  } else {
    // Это уже User ID
    userId = parseInt(usernameOrId);
  }

  // Получаем цену
  const { offerId, price } = await getStarsPrice(starsAmount);

  // Создаем заказ
  const response = await fetch('/api/v1/offers/create-order', {
    method: 'POST',
    headers: {
      'Authorization': 'your-token-here',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      offerId: offerId,
      price: price,
      transactionId: `stars_${Date.now()}`,
      customer: {
        email: "optional@example.com",
        gameUserId: userId.toString()
      }
    })
  });

  const result = await response.json();

  if (result.status === 'COMPLETED') {
    console.log(`✅ Successfully sent ${starsAmount} Stars to User ID ${userId}`);
    return result;
  } else {
    console.error(`❌ Failed to send Stars: ${result.message}`);
    throw new Error(result.message);
  }
};

// Использование:
// С username:
sendStarsByUsername('@igoryan34', 100)
  .then(order => console.log('Order created:', order.orderId))
  .catch(error => console.error('Delivery failed:', error));

// С User ID:
sendStarsByUsername('143594291', 100)
  .then(order => console.log('Order created:', order.orderId))
  .catch(error => console.error('Delivery failed:', error));

💼 B2B кейсы использования

1. Награды в играх:

JAVASCRIPT
// Наградить игрока за достижение
await sendStars(userTelegramId, 50);

2. Промо-кампании:

JAVASCRIPT
// Отправить Stars всем участникам конкурса
const winners = [143594291, 987654321, 456789123];
for (const userId of winners) {
  await sendStars(userId, 100);
}

3. Кэшбек программы:

JAVASCRIPT
// Вернуть часть покупки в виде Stars
const cashbackAmount = Math.floor(purchaseAmount * 0.05); // 5% кэшбек
const starsAmount = Math.min(cashbackAmount * 100, 1000); // конвертируем в Stars
await sendStars(userTelegramId, starsAmount);

⚡ Performance и лимиты

  • Rate limiting: 30 запросов в секунду на Telegram API
  • Minimum amount: 1 Star
  • Maximum amount: 2500 Stars за одну транзакцию
  • Retry logic: Автоматические повторы при временных ошибках
  • Delivery time: Мгновенная доставка (< 3 секунды)

🛡️ Безопасность

  • Валидация Telegram User ID перед отправкой
  • Проверка баланса GamesDrop перед созданием заказа
  • Логирование всех операций для аудита
  • Защита от дублированных транзакций через transactionId