RU

Документация

Partner Exchange API

REST JSON API для встраивания обмена криптовалют в ваш сайт, бот или сервис: каталог валют → котировка → создание обмена → отслеживание статуса.

Базовый URL https://snapex.pro/api/v1/partner

1. Обзор

Partner Exchange API позволяет проводить обмены криптовалют из вашего приложения обычными HTTP-запросами. Вы отправляете JSON — API возвращает курс, депозитный адрес и статус обмена. Этот раздел объясняет общую схему; дальше каждый шаг разобран отдельно.

Как устроен обмен

Любой обмен проходит по одной и той же схеме из четырёх шагов:

  1. Каталог (GET /assets). Вы узнаёте, какие валюты доступны и в каких пределах можно менять. Из каталога берутся короткие коды валют — usdt, btc, eth, xmr и т.д.
  2. Котировка (POST /quotes). Вы спрашиваете: «сколько получит клиент, если отправит 20 USDT в BTC?» API отвечает курсом и точными суммами. Котировка ни к чему не обязывает и действует 2 минуты.
  3. Создание обмена (POST /exchanges). Вы подтверждаете котировку — API создаёт заявку и возвращает депозитный адрес, на который клиент должен перевести средства.
  4. Статус (GET /exchanges/{quote_id}). Вы периодически опрашиваете API и узнаёте, дошёл ли депозит и отправлены ли средства клиенту.

Что нужно для начала работы

  1. Аккаунт в кабинете партнёра.
  2. Одобренная заявка на доступ к API (подаётся в кабинете, рассматривается администратором).
  3. API-ключ вида spx_… — выпускается в кабинете после одобрения. Ключ показывается только один раз при выпуске или перевыпуске: сразу сохраните его в надёжном месте.

Методы

Метод Путь Успешный HTTP-код Назначение
GET /assets 200 Каталог валют и лимитов
POST /quotes 201 Котировка (расчёт курса и сумм)
POST /exchanges 201 Создание обмена, получение депозитного адреса
GET /exchanges/{quote_id} 200 Текущий статус котировки или обмена

Формат данных

  • Все запросы и ответы — JSON в кодировке UTF-8.
  • Все денежные суммы передаются строками: "20", "0.000312". Разделитель дробной части — точка. Строки используются намеренно: числа с плавающей точкой теряют точность на криптовалютных суммах.
  • Даты — в формате ISO-8601 с часовым поясом, например 2026-07-27T13:02:00+00:00.

Заголовки каждого запроса

X-API-Key: spx_ваш_ключ
Content-Type: application/json   (только для POST)
Accept: application/json

Ключевые правила

  • Котировка действует 2 минуты (поле expires_at) — создать обмен нужно до истечения этого срока.
  • Не более 1 запроса с одного IP-адреса раз в 7 секунд по всем методам; при превышении — HTTP 429 (подробнее в разделе «Ошибки и лимиты»).
  • Повторный вызов создания обмена с теми же параметрами безопасен: дубль не создастся, вернётся тот же обмен.

2. Аутентификация

Каждый запрос к API должен содержать заголовок X-API-Key с вашим ключом. Никаких токенов, подписей и сессий — только этот заголовок.

GET https://snapex.pro/api/v1/partner/assets
X-API-Key: spx_ваш_ключ
Accept: application/json

Где взять ключ

Кабинет партнёра → вкладка «API» → «Выпустить ключ». Ключ начинается с spx_ и показывается один раз. При перевыпуске старый ключ немедленно перестаёт действовать.

Ошибки аутентификации

HTTP error Причина Что делать
401 unauthorized Заголовок X-API-Key отсутствует или ключ неверный Проверьте, что заголовок передаётся и ключ скопирован целиком
403 api_access_pending Заявка на доступ ещё на рассмотрении Дождитесь одобрения администратором
403 api_not_approved Доступ к API не одобрен Свяжитесь с поддержкой

3. Каталог валют — GET /assets

Справочник доступных валют и лимитов на сумму отправки. С него начинается интеграция: отсюда берутся коды валют для котировок и границы допустимых сумм. Успешный ответ — HTTP 200.

API принимает только короткие коды из поля code этого каталога (usdt, btc, eth, xmr и т.д.). Внутренние идентификаторы блокчейнов передавать нельзя. Каталог меняется редко — его можно кешировать на своей стороне на 5–10 минут.

Пример запроса

GET https://snapex.pro/api/v1/partner/assets
X-API-Key: spx_ваш_ключ
Accept: application/json

Пример ответа

{
  "assets": [
    {
      "code": "usdt",
      "network": "TRON",
      "symbol": "USDT",
      "name": "USDT TRON",
      "min_amount": "10",
      "max_amount": "5000",
      "min_usd": "10",
      "max_usd": "5000"
    },
    {
      "code": "btc",
      "network": "Bitcoin",
      "symbol": "BTC",
      "name": "BTC",
      "min_amount": "0.000085",
      "max_amount": "0.0425",
      "min_usd": "10",
      "max_usd": "5000"
    }
  ]
}

Поля ответа

Поле Описание
assets[].code Короткий код валюты. Именно его вы передаёте в from_asset_id и to_asset_id
assets[].network Блокчейн-сеть (TRON, Bitcoin, Ethereum и т.д.)
assets[].symbol Тикер валюты (USDT, BTC…)
assets[].name Человекочитаемое название
assets[].min_amount / max_amount Минимальная и максимальная сумма отправки в единицах валюты (пересчитаны из USD-лимитов по текущему курсу)
assets[].min_usd / max_usd Те же лимиты в долларах США

Лимиты в USD по типу маршрута

Лимиты зависят от того, участвует ли в обмене Monero (XMR). Проверяется сумма отправки клиента в долларовом эквиваленте.

Маршрут Мин. USD Макс. USD
Обычный обмен (TOKEN ↔ TOKEN) $10 $7000
Отправка XMR (XMR → TOKEN) $10 $1000
Получение XMR (TOKEN → XMR) $10 $1000

Актуальный каталог

Таблица ниже — те же данные, что возвращает GET /assets, для быстрой сверки.

Код в API Сеть Валюта Мин. отправка Макс. отправка Мин. USD Макс. USD
aave APTOS AAVE 0.05911913 41.38338753 $10 $7000
btc_aptos APTOS BTC 0.00012054 0.08437395 $10 $7000
doge APTOS DOGE 116.24257501 81369.80250387 $10 $7000
eth APTOS ETH 0.00398663 2.79063463 $10 $7000
link APTOS LINK 0.76569679 535.98774885 $10 $7000
sol APTOS SOL 0.0909091 63.63636364 $10 $7000
uni APTOS UNI 1.30890053 916.23036649 $10 $7000
xrp APTOS XRP 7.142858 5000 $10 $7000
zec APTOS ZEC 0.00815222 5.70655275 $10 $7000
avax Avalanche AVAX 0.96432016 675.024108 $10 $7000
cfi Base CFI 15268.57422054 10688001.9543775 $10 $7000
btc Bitcoin BTC 0.00012054 0.08437395 $10 $7000
aster BNB Chain ASTER 14.01243183 9808.70228066 $10 $7000
aurora BNB Chain AURORA 163.17206495 114220.44545974 $10 $7000
bnb BNB Chain BNB 0.01335595 9.34916459 $10 $7000
usdc HYPERCORE USDC 10.00325106 7002.27573962 $10 $7000
mon Monad MON 395.30801017 276715.60711602 $10 $7000
xmr Monero XMR 0.0191703 1.91702909 $10 $1000
op Optimism OP 70.13065341 49091.45738511 $10 $7000
usdt0 Optimism USDT0 10.00953 7006.67035 $10 $7000
pol Polygon POL 97.83969944 68487.78960551 $10 $7000
rhea Solana RHEA 119.41011404 83587.07982566 $10 $7000
strk Solana STRK 86.68891683 60682.24177539 $10 $7000
zec_solana Solana ZEC 0.00815222 5.70655275 $10 $7000
xlm Stellar XLM 50.9325755 35652.8028196 $10 $7000
gram TON GRAM 6.84931507 4794.52054795 $10 $7000
usdt TRON USDT 10.008568 7005.997134 $10 $7000
okb X Layer OKB 0.07948494 55.63945632 $10 $7000

4. Котировка — POST /quotes

Рассчитывает курс и точные суммы обмена. Ничего не создаёт и ни к чему не обязывает: депозитный адрес не выделяется, средства не резервируются. Успешный ответ — HTTP 201. Котировка действует 2 минуты.

Два режима: side=send и side=receive

Параметр side определяет, какая из двух сумм фиксируется:
side=send — «клиент отправляет ровно X, сколько он получит?» Сумма amount указывается в валюте отправки (from).
side=receive — «клиент хочет получить ровно Y, сколько ему нужно отправить?» Сумма amount указывается в валюте получения (to).

Режим amount — в какой валюте amount_usd
side=send В валюте from_asset_id (сколько отправляет клиент) Разрешён: сумма отправки в долларах вместо amount
side=receive В валюте to_asset_id (сколько получает клиент) Запрещён — только amount

Передавайте либо amount, либо amount_usd — что-то одно. Оба сразу — ошибка 422.

Пример запроса

POST https://snapex.pro/api/v1/partner/quotes
Content-Type: application/json
X-API-Key: spx_ваш_ключ

{
  "from_asset_id": "usdt",
  "to_asset_id": "btc",
  "side": "send",
  "amount": "20",
  "recipient_address": "bc1qexampleaddress"
}

Параметры запроса

Поле Обязательно Описание
from_asset_id Да Код валюты, которую отдаёт клиент (из каталога GET /assets)
to_asset_id Да Код валюты, которую получает клиент. Должен отличаться от from_asset_id
side Да send или receive — см. таблицу выше
amount Да, если нет amount_usd Сумма строкой, например "20" или "0.0005". При send — в валюте from, при receive — в валюте to
amount_usd Нет Только при side=send: сумма отправки в долларах, например "100". Взаимоисключим с amount
recipient_address Да Адрес кошелька клиента в сети валюты получения (to). Нужен уже на этапе котировки — по нему проверяется корректность маршрута. Допустим синоним recipient

Пример ответа

{
  "quote_id": "pq_abc123",
  "status": "quoted",
  "side": "send",
  "from_symbol": "USDT",
  "to_symbol": "BTC",
  "from_network": "TRON",
  "to_network": "Bitcoin",
  "request_amount": "20",
  "send_amount": "20",
  "receive_amount": "0.000312",
  "amount_in_usd": "20",
  "amount_out_usd": "19.85",
  "expires_at": "2026-07-27T13:02:00+00:00"
}

Поля ответа

Поле Описание
quote_id Идентификатор котировки (pq_…). Понадобится для создания обмена и проверки статуса
status quoted — котировка активна, обмен ещё не создан
side Режим фиксации суммы из запроса
from_symbol / to_symbol Тикеры валют отдачи и получения
from_network / to_network Сети валют
request_amount Сумма из вашего запроса
send_amount Сколько клиент должен отправить
receive_amount Сколько клиент получит
amount_in_usd / amount_out_usd Долларовая оценка сумм отправки и получения
request_amount_usd Присутствует, только если в запросе был amount_usd
expires_at Момент истечения котировки (ISO-8601). После него создать обмен по этому quote_id нельзя

5. Создание обмена — POST /exchanges

Превращает котировку в реальный обмен: создаётся заявка и возвращается депозитный адрес для перевода клиента. Вызывайте до истечения котировки (2 минуты). Успешный ответ — HTTP 201.

Пример запроса

POST https://snapex.pro/api/v1/partner/exchanges
Content-Type: application/json
X-API-Key: spx_ваш_ключ

{
  "quote_id": "pq_abc123",
  "recipient_address": "bc1qexampleaddress"
}

Параметры запроса

Поле Обязательно Описание
quote_id Да Идентификатор из ответа POST /quotes
recipient_address Да Адрес выплаты клиенту. Обычно тот же, что был в котировке. Допустим синоним recipient

Что происходит при вызове

  1. API находит вашу котировку и проверяет, что она не истекла.
  2. Курс перепроверяется по рынку. Если за прошедшее время он ухудшился более чем на 2% относительно котировки — обмен не создаётся, возвращается 422 (просто запросите новую котировку).
  3. Создаётся заявка и выделяется депозитный адрес.
  4. В ответе приходит блок deposit — адрес и сумма, которую клиент должен перевести.

Пример ответа

{
  "quote_id": "pq_abc123",
  "status": "awaiting_deposit",
  "side": "send",
  "from_symbol": "USDT",
  "to_symbol": "BTC",
  "from_network": "TRON",
  "to_network": "Bitcoin",
  "request_amount": "20",
  "send_amount": "20",
  "receive_amount": "0.000312",
  "amount_in_usd": "20",
  "amount_out_usd": "19.85",
  "expires_at": "2026-07-27T13:02:00+00:00",
  "deposit": {
    "asset": "USDT",
    "amount": "20",
    "address": "TXyz…",
    "amount_usd": "20"
  },
  "exchange": {
    "public_id": "ex_…",
    "status": "awaiting_deposit",
    "recipient_address": "bc1qexampleaddress"
  }
}

Новые поля по сравнению с котировкой

Поле Описание
status Обычно awaiting_deposit — ждём перевод клиента. Значение quoting означает, что депозитный адрес ещё формируется: опросите статус чуть позже
deposit.asset Валюта, которую должен перевести клиент
deposit.amount Точная сумма перевода
deposit.address Депозитный адрес — покажите его клиенту
deposit.amount_usd Долларовый эквивалент (если доступен)
exchange.public_id Публичный идентификатор обмена
exchange.status Статус заявки (совпадает с верхнеуровневым status)
exchange.recipient_address Адрес выплаты клиенту

Повторные вызовы (идемпотентность)

Если соединение оборвалось и вы не получили ответ — просто повторите запрос с теми же quote_id и recipient_address. Дубль не создастся: API вернёт уже существующий обмен. Изменить recipient_address после создания нельзя — при попытке вернётся 422.

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

  • 409 quote_expired — котировка истекла (прошло больше 2 минут). Запросите новую через POST /quotes.
  • 422 validation_error — невалидные параметры; попытка изменить recipient_address при повторе; либо курс сдвинулся более чем на 2% — запросите новую котировку.
  • 404 not_found — quote_id не существует или принадлежит другому партнёру.
  • 503 upstream_unavailable — временный сбой у поставщика ликвидности. Повторите позже с той же котировкой (если не истекла) или новой.

6. Статус — GET /exchanges/{quote_id}

Возвращает текущее состояние котировки или обмена. Формат ответа полностью совпадает с ответом создания обмена. Успешный ответ — HTTP 200. Опрашивайте не чаще раза в 7 секунд.

Пример запроса

GET https://snapex.pro/api/v1/partner/exchanges/pq_abc123
X-API-Key: spx_ваш_ключ
Accept: application/json

Значения поля status

Значение Что означает Что делать
quoted Есть только котировка, обмен не создан Создать обмен до expires_at или запросить новую котировку
quoting Обмен создаётся, депозитный адрес формируется Опросить статус ещё раз через несколько секунд
awaiting_deposit Ждём перевод клиента на депозитный адрес Показать клиенту адрес и сумму из блока deposit
processing Депозит получен, обмен выполняется Ждать, продолжая опрос
completed Обмен завершён, средства отправлены клиенту Финальный статус — опрос можно прекратить
error Обмен завершился ошибкой Финальный статус. Свяжитесь с поддержкой, указав exchange.public_id
cancelled Обмен отменён Финальный статус
expired Котировка истекла, обмен не был создан Финальный статус. Запросить новую котировку

Финальные статусы: completed, error, cancelled, expired. После них состояние не меняется — дальнейший опрос не нужен.

При status=completed в блоке exchange может появиться поле partner_api_earning_usd — ваш заработок по этой сделке в долларах.

Пример ответа

{
  "quote_id": "pq_abc123",
  "status": "completed",
  "side": "send",
  "from_symbol": "USDT",
  "to_symbol": "BTC",
  "from_network": "TRON",
  "to_network": "Bitcoin",
  "request_amount": "20",
  "send_amount": "20",
  "receive_amount": "0.000312",
  "amount_in_usd": "20",
  "amount_out_usd": "19.85",
  "expires_at": "2026-07-27T13:02:00+00:00",
  "deposit": {
    "asset": "USDT",
    "amount": "20",
    "address": "TXyz…",
    "amount_usd": "20"
  },
  "exchange": {
    "public_id": "ex_…",
    "status": "completed",
    "recipient_address": "bc1qexampleaddress",
    "partner_api_earning_usd": "0.20"
  }
}

7. Ошибки и лимиты

Все ошибки возвращаются в едином JSON-формате. Код HTTP-ответа дублирует смысл поля error — можно ориентироваться на любой из них.

{
  "ok": false,
  "error": "validation_error",
  "message": "Человекочитаемое пояснение на английском"
}

Справочник ошибок

HTTP error Причина Что делать
401 unauthorized Отсутствует или неверный X-API-Key Проверить заголовок и ключ
403 api_access_pending Заявка на доступ на рассмотрении Дождаться одобрения
403 api_not_approved Доступ к API не одобрен Связаться с поддержкой
404 not_found Неизвестный или чужой quote_id Проверить идентификатор
409 quote_expired Котировка старше 2 минут Запросить новую котировку
422 validation_error Невалидные параметры, нарушение лимитов или сдвиг курса > 2% Прочитать message, исправить запрос или взять новую котировку
429 rate_limited Превышена частота запросов Подождать и повторить
503 upstream_unavailable Временный сбой поставщика ликвидности Повторить позже

Лимиты частоты запросов

Область Лимит
Все методы, на один IP-адрес 1 запрос в 7 секунд
POST /quotes, на партнёра 15 запросов в минуту
POST /exchanges, на партнёра 10 запросов в минуту
GET /assets и GET /exchanges/{quote_id}, на партнёра 120 запросов в минуту

8. Пример: обмен от начала до конца

Полный сценарий: клиент отдаёт 20 USDT (сеть TRON) и получает BTC на свой биткоин-адрес. Замените YOUR_KEY на ваш API-ключ.

Шаг 1. Запросить котировку

curl -sS -X POST 'https://snapex.pro/api/v1/partner/quotes' \
  -H 'X-API-Key: YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -d '{
    "from_asset_id": "usdt",
    "to_asset_id": "btc",
    "side": "send",
    "amount": "20",
    "recipient_address": "bc1qexample"
  }'

В ответе придёт quote_id (pq_…) и суммы. Покажите клиенту receive_amount — столько BTC он получит. У вас 2 минуты на следующий шаг.

Шаг 2. Создать обмен

curl -sS -X POST 'https://snapex.pro/api/v1/partner/exchanges' \
  -H 'X-API-Key: YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -d '{
    "quote_id": "pq_ИЗ_ШАГА_1",
    "recipient_address": "bc1qexample"
  }'

В ответе появится блок deposit с адресом и суммой. Покажите клиенту deposit.address и deposit.amount — он должен перевести ровно эту сумму на этот адрес.

Шаг 3. Отслеживать статус

curl -sS 'https://snapex.pro/api/v1/partner/exchanges/pq_ИЗ_ШАГА_1' \
  -H 'X-API-Key: YOUR_KEY' \
  -H 'Accept: application/json'

Повторяйте запрос с паузой 7–10 секунд. Когда клиент переведёт средства, статус сменится на processing, а затем на completed — средства отправлены клиенту. Финальные статусы: completed, error, cancelled, expired.

Тот же сценарий на Python

import time
import requests

API = "https://snapex.pro/api/v1/partner"
HEADERS = {
    "X-API-Key": "YOUR_KEY",
    "Content-Type": "application/json",
    "Accept": "application/json",
}

# Шаг 1. Котировка: клиент отправляет 20 USDT, получает BTC
quote = requests.post(f"{API}/quotes", headers=HEADERS, json={
    "from_asset_id": "usdt",
    "to_asset_id": "btc",
    "side": "send",
    "amount": "20",
    "recipient_address": "bc1qexample",
}).json()
print("Клиент получит:", quote["receive_amount"], quote["to_symbol"])

# Шаг 2. Создание обмена (в течение 2 минут после котировки)
exchange = requests.post(f"{API}/exchanges", headers=HEADERS, json={
    "quote_id": quote["quote_id"],
    "recipient_address": "bc1qexample",
}).json()
deposit = exchange["deposit"]
print("Клиент должен перевести:", deposit["amount"], deposit["asset"])
print("На адрес:", deposit["address"])

# Шаг 3. Опрос статуса до финального
while True:
    time.sleep(10)  # не чаще 1 запроса в 7 секунд
    state = requests.get(
        f"{API}/exchanges/{quote['quote_id']}", headers=HEADERS
    ).json()
    print("Статус:", state["status"])
    if state["status"] in ("completed", "error", "cancelled", "expired"):
        break

Частые ошибки новичков

  • Сумма передана числом, а не строкой. Правильно: "amount": "20", а не "amount": 20.
  • При side=receive сумма указана в валюте отправки. При receive amount — это сумма в валюте получения (to).
  • Обмен создаётся спустя больше 2 минут после котировки — придёт 409 quote_expired. Запрашивайте котировку непосредственно перед созданием.
  • Запросы отправляются чаще раза в 7 секунд — придёт 429. Добавьте паузу между запросами.