Pers ShopAPI реселлераВойти

API реселлера

Всё, что есть в кабинете, — запросами: каталог и цены, проверка ID игрока, заказы, пополнение баланса и вебхуки о выполнении. Суммы — в сомони, цены — ваши, реселлерские.

Адрес

https://reseller.persshop.com/api/v1

Ключ

Authorization: Bearer rs_live_…

Лимит

240 запросов в минуту на ключ (429 и retry-after)

OpenAPI

openapi.json — для Postman и Swagger

Как устроены ответы

Успех — {"ok": true, …}, ошибка — {"ok": false, "error": {"code", "message"}}. В каждом ответе есть requestId — назовите его поддержке, если что-то пошло не так.

GET/me

Кабинет и баланс

Чей это ключ, статус кабинета, баланс и на какой цене кабинет — общей реселлерской или личной.

Запрос

curl -X GET https://reseller.persshop.com/api/v1/me \
  -H "Authorization: Bearer $PERSSHOP_KEY"

Ответ

{
  "ok": true,
  "account": {
    "id": "…",
    "number": 1043,
    "email": "shop@example.com",
    "contactName": "Фарход",
    "company": "Farhod Store",
    "status": "active"
  },
  "key": {
    "id": "rs_live_…",
    "name": "Бот",
    "webhookUrl": null
  },
  "balance": {
    "availableTjs": 1250.4,
    "heldTjs": 0,
    "currency": "TJS"
  },
  "pricing": {
    "priceList": "default"
  }
}
GET/balance

Баланс

Сколько можно потратить прямо сейчас.

Запрос

curl -X GET https://reseller.persshop.com/api/v1/balance \
  -H "Authorization: Bearer $PERSSHOP_KEY"

Ответ

{
  "ok": true,
  "availableTjs": 1250.4,
  "heldTjs": 0,
  "currency": "TJS"
}
GET/catalog

Каталог

Товары с ценой «от» — вашей и розничной в магазине. Поиск и фильтр по виду. imageUrl — обложка, iconUrl — квадратная иконка (может быть null), обе полными адресами.

qqueryПоиск по названию: free fire, pubg, steam…
kindquerytopup, steam_topup, game_key, gift_card, steam_gift, telegram_stars, telegram_premium
limitquery1–100, по умолчанию 50
offsetqueryСдвиг для следующей страницы

Запрос

curl -X GET https://reseller.persshop.com/api/v1/catalog \
  -H "Authorization: Bearer $PERSSHOP_KEY"

Ответ

{
  "ok": true,
  "total": 1,
  "limit": 50,
  "offset": 0,
  "items": [
    {
      "id": "free-fire",
      "kind": "topup",
      "title": "Free Fire",
      "subtitle": "Алмазы — регион аккаунта на выбор",
      "imageUrl": "https://persshop.com/covers/free-fire.webp",
      "iconUrl": "https://persshop.com/game-icons/free-fire.webp",
      "regionCount": 13,
      "fromPriceTjs": 8.1,
      "retailFromTjs": 9.45
    }
  ]
}
GET/catalog/{id}

Товар и номиналы

Номиналы с вашей ценой (priceTjs) и розницей магазина (retailPriceTjs), какие поля прислать при заказе (fields) и можно ли проверить ID (idCheckField). Картинки — полными адресами: imageUrl — обложка, iconUrl — квадратная иконка игры (может быть null), offers[].imageUrl — картинка номинала, как на витрине. Цены свежие — спрошены у поставщика.

id*pathid товара из каталога, например free-fire

Запрос

curl -X GET https://reseller.persshop.com/api/v1/catalog/free-fire \
  -H "Authorization: Bearer $PERSSHOP_KEY"

Ответ

{
  "ok": true,
  "category": {
    "id": "free-fire",
    "kind": "topup",
    "title": "Free Fire",
    "fields": [
      {
        "key": "player_id",
        "label": "ID игрока",
        "type": "text",
        "options": null
      }
    ],
    "idCheckField": "player_id",
    "imageUrl": "https://persshop.com/covers/free-fire.webp",
    "iconUrl": "https://persshop.com/game-icons/free-fire.webp",
    "offers": [
      {
        "offerId": "110_diamonds",
        "title": "100 алмазов",
        "priceTjs": 8.1,
        "retailPriceTjs": 9.45,
        "imageUrl": "https://persshop.com/items/ff/diamonds-1.webp"
      }
    ],
    "steamTopup": null
  }
}
GET/prices

Цены пачкой

Цены по многим товарам одним запросом — до 50. Удобно держать прайс бота в актуальном виде. С картинками, как в /catalog/{id}.

ids*queryid товаров через запятую: free-fire,pubg-uc

Запрос

curl -X GET https://reseller.persshop.com/api/v1/prices \
  -H "Authorization: Bearer $PERSSHOP_KEY"

Ответ

{
  "ok": true,
  "currency": "TJS",
  "categories": [
    {
      "id": "free-fire",
      "found": true,
      "title": "Free Fire",
      "imageUrl": "https://persshop.com/covers/free-fire.webp",
      "iconUrl": "https://persshop.com/game-icons/free-fire.webp",
      "offers": [
        {
          "offerId": "110_diamonds",
          "title": "100 алмазов",
          "priceTjs": 8.1,
          "retailPriceTjs": 9.45,
          "imageUrl": "https://persshop.com/items/ff/diamonds-1.webp"
        }
      ]
    }
  ]
}
POST/check-id

Проверить ID игрока

Ник по ID до оплаты — для игр, где idCheckField не null. valid:false — такого ID нет; 503 check_unavailable_now — проверка сейчас не работает (это не ответ про ID).

Запрос

curl -X POST https://reseller.persshop.com/api/v1/check-id \
  -H "Authorization: Bearer $PERSSHOP_KEY" \
  -H "Content-Type: application/json" \
  -d '{"categoryId":"free-fire","fields":{"player_id":"123456789"}}'

Ответ

{
  "ok": true,
  "valid": true,
  "playerName": "Farhod_07",
  "region": "CIS"
}
POST/ordersсписывает деньги

Оформить заказ

Списывает вашу цену с баланса и сразу выполняет заказ. Цену считаем мы — в запросе только ЧТО купить: offerId (или amountUsd для Steam) и поля. Заголовок Idempotency-Key обязателен: повтор с тем же ключом вернёт тот же ответ (replayed: true), а не спишет второй раз. Ошибки, при которых деньги не тронуты (400, 402, 404, 409), освобождают ключ.

Idempotency-Key*header8–128 символов, свой на каждый заказ — например UUID

Запрос

curl -X POST https://reseller.persshop.com/api/v1/orders \
  -H "Authorization: Bearer $PERSSHOP_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"categoryId":"free-fire","offerId":"110_diamonds","fields":{"player_id":"123456789"}}'

Ответ

{
  "ok": true,
  "order": {
    "id": "8b6c0d7e-…",
    "number": 18234,
    "categoryId": "free-fire",
    "offerId": "110_diamonds",
    "offerTitle": "100 алмазов",
    "fields": {
      "player_id": "123456789"
    },
    "priceTjs": 8.1,
    "status": "fulfilled",
    "codes": [],
    "error": null,
    "createdAt": "2026-10-07T12:00:00.000Z",
    "updatedAt": "2026-10-07T12:00:06.000Z"
  }
}
GET/orders

Список заказов

Ваши заказы, новые сверху, с total — для сверки после обрыва связи.

statusquerypending, fulfilling, fulfilled, failed, refunded
limitquery1–100, по умолчанию 50
offsetqueryСдвиг

Запрос

curl -X GET https://reseller.persshop.com/api/v1/orders \
  -H "Authorization: Bearer $PERSSHOP_KEY"

Ответ

{
  "ok": true,
  "total": 1,
  "limit": 50,
  "offset": 0,
  "orders": [
    {
      "id": "8b6c0d7e-…",
      "number": 18234,
      "categoryId": "free-fire",
      "offerId": "110_diamonds",
      "offerTitle": "100 алмазов",
      "fields": {
        "player_id": "123456789"
      },
      "priceTjs": 8.1,
      "status": "fulfilled",
      "codes": [],
      "error": null,
      "createdAt": "2026-10-07T12:00:00.000Z",
      "updatedAt": "2026-10-07T12:00:06.000Z"
    }
  ]
}
GET/orders/{id}

Заказ

Заказ по id или короткому номеру. У подарочных карт и ключей игр коды — в codes.

id*pathid заказа или его номер

Запрос

curl -X GET https://reseller.persshop.com/api/v1/orders/1042 \
  -H "Authorization: Bearer $PERSSHOP_KEY"

Ответ

{
  "ok": true,
  "order": {
    "id": "8b6c0d7e-…",
    "number": 18234,
    "categoryId": "free-fire",
    "offerId": "110_diamonds",
    "offerTitle": "100 алмазов",
    "fields": {
      "player_id": "123456789"
    },
    "priceTjs": 8.1,
    "status": "fulfilled",
    "codes": [],
    "error": null,
    "createdAt": "2026-10-07T12:00:00.000Z",
    "updatedAt": "2026-10-07T12:00:06.000Z"
  }
}
GET/transactions

Движение по балансу

Пополнения, покупки, возвраты — новые сверху.

limitquery1–200, по умолчанию 50

Запрос

curl -X GET https://reseller.persshop.com/api/v1/transactions \
  -H "Authorization: Bearer $PERSSHOP_KEY"

Ответ

{
  "ok": true,
  "transactions": [
    {
      "id": "…",
      "type": "purchase",
      "amountTjs": -8.1,
      "balanceAfterTjs": 1242.3,
      "orderId": "8b6c0d7e-…",
      "note": "Покупка",
      "createdAt": "2026-10-07T12:00:00.000Z"
    }
  ]
}
POST/topups

Пополнить баланс

Счёт на перевод с карты любого банка. Переведите ТОЧНО transferExactTjs на карту из transfer: хвост в дирамах — номер платежа, по нему перевод зачисляется сам, обычно за пару минут.

Запрос

curl -X POST https://reseller.persshop.com/api/v1/topups \
  -H "Authorization: Bearer $PERSSHOP_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amountTjs":1000}'

Ответ

{
  "ok": true,
  "topup": {
    "id": "52731",
    "status": "pending",
    "amountTjs": 1000,
    "transferExactTjs": 1000.37,
    "expiresAt": "2026-10-07T12:30:00.000Z"
  },
  "transfer": {
    "cardNumber": "…",
    "holderName": "…",
    "bank": "Алиф"
  }
}
GET/topups/{id}

Статус пополнения

pending — ждём перевод; paid — деньги на балансе; expired, cancelled — счёт закрыт.

id*pathid счёта

Запрос

curl -X GET https://reseller.persshop.com/api/v1/topups/52731 \
  -H "Authorization: Bearer $PERSSHOP_KEY"

Ответ

{
  "ok": true,
  "topup": {
    "id": "52731",
    "status": "paid",
    "amountTjs": 1000,
    "transferExactTjs": 1000.37
  }
}
DELETE/topups/{id}

Отменить пополнение

Закрывает незавершённый счёт — например, чтобы выставить другую сумму: такой счёт держать можно один. Если перевод всё же уйдёт после отмены, он не потеряется, но зачислится не сам — напишите в поддержку.

id*pathid счёта

Запрос

curl -X DELETE https://reseller.persshop.com/api/v1/topups/52731 \
  -H "Authorization: Bearer $PERSSHOP_KEY"

Ответ

{
  "ok": true,
  "topup": {
    "id": "52731",
    "status": "cancelled",
    "amountTjs": 1000,
    "transferExactTjs": 1000.37
  }
}
PUT/webhook

Вебхук

Куда сообщать о конце заказа: события order.fulfilled и order.refunded с заказом в теле. Подпись — заголовок x-persshop-signature: t=<сек>,v1=<hex HMAC-SHA256(secret, "<t>.<тело>")>; отбрасывайте всё старше 5 минут. GET — настройки и последняя доставка, POST {action: "test"} — проверочное событие ping, {action: "rotate_secret"} — новый секрет.

Запрос

curl -X PUT https://reseller.persshop.com/api/v1/webhook \
  -H "Authorization: Bearer $PERSSHOP_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://your-bot.example/persshop"}'

Ответ

{
  "ok": true,
  "webhook": {
    "url": "https://your-bot.example/persshop",
    "secret": "whsec_…",
    "lastAt": null,
    "lastResult": null,
    "failsInRow": 0
  }
}

Коды ошибок

unauthorized401Нет ключа, ключ неверный или отозван.
account_inactive403Кабинет на проверке, отклонён или заблокирован.
rate_limited429Больше лимита запросов в минуту; ждите retry-after секунд.
not_found404Товара или заказа нет (или он не ваш).
missing_field400Не заполнено поле товара — его ключ в error.field.
offer_not_found400Такого номинала нет — проверьте offerId.
insufficient_balance402Не хватает баланса — пополните и повторите.
item_unavailable409Поставщик сейчас не выдаёт этот товар.
fulfillment_failed502Поставщик не выполнил заказ; деньги уже вернулись на баланс.
idempotency_key_required400Нет заголовка Idempotency-Key.
idempotency_key_reuse422Этот ключ уже был у другого заказа.
in_progress409Заказ по этому ключу ещё выполняется — повторите через секунды.
bad_amount400Сумма пополнения не указана или вне пределов.
topup_pending409Уже есть незавершённый перевод — его счёт и карта в error.topup и error.transfer.
topup_unavailable409Пополнение сейчас закрыто (ночное окно банка и т. п.) — причина в message.
check_unavailable_now503Проверка ID у поставщика сейчас не отвечает — повторите позже.
too_many_failed_attempts429Слишком много запросов с неверным ключом с вашего адреса.
bad_json400Тело запроса — не JSON.
body_too_large413Тело запроса больше 64 КБ.