Swapnoir
RU

Публичный API · v1 · Бесплатно

API Swapnoir

Актуальные курсы обмена, поддерживаемые валюты и отслеживание заказов для вашего кошелька, бота или сайта. Только чтение, без API-ключа и без аккаунта.

Базовый URL
https://swapnoir.com/api/v1
Аутентификация
Не требуется
Формат
JSON, UTF-8
Ошибки
RFC 9457

Обзор

API Swapnoir даёт вашему приложению те же актуальные данные, которые использует обменник swapnoir.com. Это небольшой REST API поверх HTTPS с тремя эндпоинтами; он возвращает JSON и описан в файле OpenAPI 3.1, который можно загрузить в Postman, Insomnia, Scalar или генератор кода.

Показывайте актуальные курсы

Ценовые виджеты, калькуляторы и боты. Оценки уже включают все комиссии за выплату.

Направляйте пользователей к обмену

Открывайте предзаполненный обмен на swapnoir.com из своего приложения одной ссылкой.

Отслеживайте заказы

Отслеживайте обмен по ID заказа и уведомляйте пользователей о его завершении.

Быстрый старт

Регистрация не нужна. Выполните эти команды в терминале; каждая работает сама по себе.

  1. Получите список доступных валют. Используйте id каждой валюты в остальных запросах.
    curl "https://swapnoir.com/api/v1/currencies"
  2. Получите актуальную оценку. Сколько XMR можно получить за 0.01 BTC с учётом комиссий?
    curl "https://swapnoir.com/api/v1/estimate?from=BTC&to=XMR&amount=0.01"
  3. Направьте пользователя к обмену и отслеживайте его. Пользователь завершает оформление на swapnoir.com и получает страницу заказа. По ID заказа вы сможете следить за ним.
    curl "https://swapnoir.com/api/v1/orders/K7M2QX9PRT4B"

Попробуйте прямо сейчас

GET /api/v1/estimate?from=BTC&to=XMR&amount=0.01&rate=float

Запросы и данные

Базовый URLhttps://swapnoir.com/api/v1. Только HTTPS.
МетодыВсе эндпоинты используют метод GET. Параметры передаются в строке запроса или в пути.
Ответыapplication/json, UTF-8. Для ошибок используется application/problem+json.
СуммыДесятичные строки, например "0.01", чтобы не терять точность. Передавайте суммы с точкой, знаков после точки — не больше, чем decimals у валюты.
ID валютВалюта плюс сеть, например BTC, USDT-TRC20. В запросах регистр не важен; в ответах всегда верхний регистр.
ВремяISO 8601 в UTC, например 2026-10-05T12:00:00.000Z.
БраузерыCORS открыт (Access-Control-Allow-Origin: *), поэтому API можно вызывать прямо с веб-страницы. Файлы cookie не используются.
TorТакже доступен через Tor по адресу http://swapnoqyyp3mfh3hoypzmvpnau7gymt7c32tybx2qew3s7sw7bzz7aqd.onion/api/v1 — с теми же эндпоинтами и лимитами.
ВерсионированиеВерсия указана в пути. В рамках v1 мы только добавляем: новые эндпоинты, новые необязательные параметры, новые поля ответа и новые валюты, поэтому игнорируйте незнакомые поля. Всё, что может нарушить работу интеграции, выходит в новой версии, а v1 продолжает работать параллельно с ней.

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

Не требуется. Нет ни API-ключей, ни аккаунтов, ни токенов, и запросы ни к кому не привязываются. Никогда не отправляйте в API учётные данные, сид-фразы или приватные ключи — API никогда их не запрашивает.

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

Лимиты считаются для каждого подключения в скользящем окне длиной в минуту.

ЭндпоинтЗапросов в минуту
GET /currencies60
GET /estimate90
GET /orders/{id}30

Каждый ответ содержит стандартные заголовки RateLimit-Policy (например, 90;w=60) и RateLimit (например, limit=90, remaining=89, reset=60). При превышении лимита вы получите 429 с заголовком Retry-After, где указано время ожидания в секундах.

  • Кешируйте /currencies минимум на 5 минут: список меняется редко.
  • Пока пользователь вводит сумму, ждите около полсекунды после последнего нажатия клавиши, прежде чем запрашивать оценку.
  • Опрашивайте заказ не чаще раза в 10 секунд и прекращайте, когда final равно true.

Ошибки

Ошибки возвращаются в стандартном формате RFC 9457 problem details. Проверьте HTTP-статус, затем ветвите логику по code — это значение никогда не меняется. detail — понятное сообщение на английском языке, которое можно показать пользователю, а type ссылается на соответствующую строку таблицы ниже.

422 Пример
{
  "type": "https://swapnoir.com/api#error-amount_too_small",
  "title": "Amount below minimum",
  "status": 422,
  "detail": "The minimum for this pair is 0.00005799 BTC.",
  "code": "amount_too_small",
  "min_amount": "0.00005799"
}
КодHTTPЗначение
invalid_parameter400Параметр запроса отсутствует или имеет неверный формат. Его имя указано в param.
same_currency400from и to — одна и та же валюта.
receive_not_supported400Валюта to доступна только для отправки (Lightning).
amount_too_small422Сумма ниже минимума для этой пары. Минимум указан в min_amount.
pair_not_supported422Эта пара валют и сетей не поддерживается.
pair_unavailable503Для этой пары сейчас нет доступного курса. Повторите позже или попробуйте другую сумму.
not_found404Заказа с этим ID не существует, или заказ был удалён.
rate_limited429Вы достигли лимита запросов. Подождите столько секунд, сколько указано в Retry-After.
internal_error500На нашей стороне что-то пошло не так. Повторите позже.

Справочник

Список валют

GET/api/v1/currencies

Все валюты и сети, которые поддерживает Swapnoir. Токен в другой сети считается отдельной валютой, например USDT-TRC20 и USDT-ERC20. Список меняется редко; кешируйте его на несколько минут.

В примере показаны три валюты. Поля ответа ниже описывают одну валюту.

Запрос

curl "https://swapnoir.com/api/v1/currencies"
const res = await fetch("https://swapnoir.com/api/v1/currencies");
const { currencies } = await res.json();

// Currencies a user can receive
const receivable = currencies.filter((c) => c.receive);
import requests

r = requests.get("https://swapnoir.com/api/v1/currencies", timeout=10)
r.raise_for_status()
currencies = r.json()["currencies"]

Ответ

200 OK
{
  "currencies": [
    {
      "id": "BTC",
      "ticker": "BTC",
      "name": "Bitcoin",
      "network": "Bitcoin",
      "decimals": 8,
      "send": true,
      "receive": true,
      "memo": null,
      "icon_url": "https://swapnoir.com/assets/coins/btc.svg"
    },
    {
      "id": "BTC-LN",
      "ticker": "BTC",
      "name": "Bitcoin",
      "network": "Lightning",
      "decimals": 8,
      "send": true,
      "receive": false,
      "memo": null,
      "icon_url": "https://swapnoir.com/assets/coins/btc.svg"
    },
    {
      "id": "XRP",
      "ticker": "XRP",
      "name": "XRP",
      "network": "XRP Ledger",
      "decimals": 6,
      "send": true,
      "receive": true,
      "memo": "Destination tag",
      "icon_url": "https://swapnoir.com/assets/coins/xrp.svg"
    }
  ]
}
Поля ответа
ПолеТипОписание
idstringВалюта и сеть.
tickerstring
namestring
networkstring
decimalsintegerМаксимальное число знаков после точки в суммах.
sendbooleanМожно использовать как from.
receivebooleanМожно использовать как to.
memostring or nullНазвание дополнительного поля, которое в некоторых сетях требуется вместе с адресом, например Destination tag; null, если не используется.
icon_urlstring

Получить оценку

GET/api/v1/estimate

Сколько to получит пользователь за amount в from, с уже учтёнными комиссиями за обмен и комиссиями сети за выплату. Оценки рассчитываются в реальном времени и не резервируются: итоговая сумма фиксируется при создании обмена (фиксированный курс) или при подтверждении депозита (плавающий курс).

Параметры

ИмяГдеОписание
fromобязательноqueryВалюта, которую отправляет пользователь. Пример: BTC.
toобязательноqueryВалюта, которую получает пользователь. BTC-LN — только для отправки. Пример: XMR.
amountобязательноqueryСумма в from: десятичное число с точкой, знаков после точки — не больше, чем decimals у этой валюты. Пример: 0.01.
ratequeryfloat (по умолчанию) следует за рынком до подтверждения депозита. fixed фиксирует сумму в момент создания обмена. Одно из значений: float, fixed. Пример: float.

Запрос

curl "https://swapnoir.com/api/v1/estimate?from=BTC&to=XMR&amount=0.01&rate=float"
const params = new URLSearchParams({ from: "BTC", to: "XMR", amount: "0.01" });
const res = await fetch(`https://swapnoir.com/api/v1/estimate?${params}`);
const data = await res.json();

if (!res.ok) {
  // RFC 9457 problem, e.g. data.code === "amount_too_small"
  throw new Error(data.detail);
}
console.log(data.amount_to, data.to);
import requests

r = requests.get(
    "https://swapnoir.com/api/v1/estimate",
    params={"from": "BTC", "to": "XMR", "amount": "0.01"},
    timeout=10,
)
data = r.json()
if not r.ok:
    raise RuntimeError(data["code"] + ": " + data["detail"])
print(data["amount_to"], data["to"])

Ответ

200 OK
{
  "from": "BTC",
  "to": "XMR",
  "rate_type": "float",
  "amount_from": "0.01",
  "amount_to": "1.57166029",
  "rate": "157.166029",
  "usd_value": "866.32",
  "quoted_at": "2026-10-05T12:00:00.000Z"
}
422 Ниже минимума
{
  "type": "https://swapnoir.com/api#error-amount_too_small",
  "title": "Amount below minimum",
  "status": 422,
  "detail": "The minimum for this pair is 0.00005799 BTC.",
  "code": "amount_too_small",
  "min_amount": "0.00005799"
}
400 Недопустимый параметр
{
  "type": "https://swapnoir.com/api#error-invalid_parameter",
  "title": "Invalid parameter",
  "status": 400,
  "detail": "Unknown currency `DOG`. See /api/v1/currencies.",
  "code": "invalid_parameter",
  "param": "from"
}
Поля ответа
ПолеТипОписание
fromstringВалюта и сеть.
tostringЛюбая валюта, кроме доступных только для отправки.
rate_typestringТип курса
amount_fromstringСумма из запроса.
amount_tostringСумма, которую получит пользователь после всех комиссий.
ratestringКоличество to за 1 from после вычета комиссий.
usd_valuestring or nullПримерная стоимость amount_from в долларах США, если известна.
quoted_atstring

Получить заказ

GET/api/v1/orders/{id}

Текущий статус и детали обмена. ID заказа — последняя часть URL страницы заказа. Любой, у кого есть ID, может просмотреть заказ, поэтому обращайтесь с ним как с паролем. Опрашивайте не чаще раза в 10 секунд и прекращайте, когда final равно true. Заказы удаляются через 7 дней после завершения.

Параметры

ИмяГдеОписание
idобязательноpathID заказа, например K7M2QX9PRT4B.

Запрос

curl "https://swapnoir.com/api/v1/orders/K7M2QX9PRT4B"
const res = await fetch(`https://swapnoir.com/api/v1/orders/${orderId}`);
if (res.status === 404) {
  // wrong ID, or the order was deleted
}
const order = await res.json();
console.log(order.status, order.final);
import time
import requests

while True:
    r = requests.get(f"https://swapnoir.com/api/v1/orders/{order_id}", timeout=10)
    if r.status_code == 404:
        break  # wrong ID, or the order was deleted
    order = r.json()
    print(order["status"])
    if order["final"]:
        break
    time.sleep(15)

Ответ

200 OK
{
  "id": "K7M2QX9PRT4B",
  "status": "confirming",
  "final": false,
  "rate_type": "float",
  "created_at": "2026-10-05T12:00:00.000Z",
  "updated_at": "2026-10-05T12:06:12.000Z",
  "from": {
    "currency": "BTC",
    "amount": "0.01"
  },
  "to": {
    "currency": "XMR",
    "amount": "1.57166029",
    "amount_is_final": false
  },
  "deposit": {
    "address": "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
    "memo": null,
    "expires_at": null
  },
  "payout": {
    "address": "888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H",
    "memo": null
  },
  "refund": null,
  "transactions": {
    "deposit": {
      "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
      "url": "https://mempool.space/tx/e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
    },
    "payout": null
  },
  "links": {
    "order_page": "https://swapnoir.com/order/K7M2QX9PRT4B",
    "receipt": "https://swapnoir.com/order/K7M2QX9PRT4B/receipt.txt"
  }
}
404 Не найдено
{
  "type": "https://swapnoir.com/api#error-not_found",
  "title": "Not found",
  "status": 404,
  "detail": "No order with this ID. Orders are deleted 7 days after they finish.",
  "code": "not_found"
}
Поля ответа
ПолеТипОписание
idstringID заказа
statusstringСтатус заказа
finalbooleanРавно true для done, expired, refunded и failed: прекратите опрос.
rate_typestringТип курса
created_atstring
updated_atstring
fromobject
from.currencystringВалюта и сеть.
from.amountstringСумма депозита.
toobject
to.currencystringВалюта и сеть.
to.amountstring or nullОжидаемая выплата или итоговая выплата, когда amount_is_final равно true.
to.amount_is_finalboolean
depositobject
deposit.addressstring or nullКуда пользователь отправляет депозит; null, пока статус preparing.
deposit.memostring or nullМемо или тег назначения, который нужно указать при отправке депозита, если он задан.
deposit.expires_atstring or nullОтправить депозит нужно до этого времени, если оно задано.
payoutobject
payout.addressstring
payout.memostring or null
refundnull or object
refund.addressstring
refund.memostring or null
transactionsobject
transactions.depositnull or object
transactions.deposit.hashstring
transactions.deposit.urlstring or nullСсылка на обозреватель блоков, если она известна.
transactions.payoutnull or object
transactions.payout.hashstring
transactions.payout.urlstring or nullСсылка на обозреватель блоков, если она известна.
linksobject
links.order_pagestring
links.receiptstring

Руководства

Создание обмена

Обмены создаются на swapnoir.com, поэтому пользователь всегда получает собственную страницу заказа и сохраняет контроль над ней. Ваше приложение направляет пользователя туда с уже заполненными монетами и суммой:

СсылкаЧто открывается
https://swapnoir.com/exchange?from=BTC&to=XMR&amount=0.01&rate=floatОбмен на шаге ввода адреса, с актуальной оценкой. Лучше всего подходит для кнопок «Обменять сейчас».
https://swapnoir.com/?from=BTC&to=XMR&amount=0.01Главная страница с заполненной формой обмена, где пользователь ещё может изменить монеты и сумму.

Обе ссылки принимают те же параметры from, to, amount и необязательный rate, что и запрос «Получить оценку». Чтобы открыть страницу на другом языке, добавьте код языка в начало пути, например /de/exchange?….

<a href="https://swapnoir.com/exchange?from=BTC&to=XMR&amount=0.01&rate=float" rel="noopener">
  Exchange BTC to XMR on Swapnoir
</a>
  1. Пользователь вставляет адрес получения и, при желании, адрес для возврата, проходит быструю проверку безопасности и нажимает Начать обмен.
  2. Пользователь попадает на страницу своего заказа, https://swapnoir.com/order/<ID>, с адресом для депозита и суммой.
  3. Если ваше приложение должно отслеживать заказ, попросите пользователя вставить ссылку на заказ или его ID, а затем периодически вызывайте «Получить заказ».

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

Обычный обмен проходит этапы awaiting → confirming → exchanging → sending → done. Показывайте пользователю status своими словами и прекращайте опрос, как только final станет true.

СтатусФинальныйЗначение
preparingНетАдрес для депозита готовится. Обычно он появляется в течение нескольких минут.
awaitingНетОжидание депозита. Отправляйте, только пока заказ в этом статусе и до deposit.expires_at.
confirmingНетДепозит обнаружен и ожидает подтверждений сети.
exchangingНетДепозит подтверждён, идёт обмен.
sendingНетОбменянные монеты отправляются на адрес для выплаты.
processingНетВ процессе. Используется, когда более точный статус неизвестен.
doneДаЗавершён. Выплата отправлена; см. transactions.payout.
expiredДаДепозит не поступил вовремя. Опоздавший депозит всё ещё можно обменять или вернуть через поддержку.
holdНетПриостановлен для плановой проверки. Пользователю следует связаться с поддержкой и указать ID заказа.
attentionНетЧто-то требует проверки, например депозит в неверной сумме. Пользователю следует связаться с поддержкой.
refundingНетДепозит возвращается на адрес для возврата.
refundedДаДепозит возвращён.
failedДаОбмен не удалось завершить. Пользователю следует связаться с поддержкой.

Поддерживаемые валюты

Тот же список, что возвращает «Список валют». Со временем добавляются новые валюты, поэтому получайте список через API, а не прописывайте его в коде.

IDВалютаСетьЗнаков после точкиПолучениеМемо
BTCBitcoinBitcoin8Да–
XMRMoneroMonero12Да–
ETHEthereumEthereum8Да–
USDT-TRC20TetherTron (TRC20)6Да–
USDT-ERC20TetherEthereum (ERC20)6Да–
USDT-SOLTetherSolana6Да–
USDC-ERC20USD CoinEthereum (ERC20)6Да–
LTCLitecoinLitecoin8Да–
SOLSolanaSolana9Да–
BTC-LNBitcoin LightningLightning8Только отправка–
TRXTronTron6Да–
BNBBNBBNB Smart Chain (BEP20)8Да–
DOGEDogecoinDogecoin8Да–
ZECZcashZcash8Да–
BCHBitcoin CashBitcoin Cash8Да–
DASHDashDash8Да–
XRPXRPXRP Ledger6ДаТег назначения

Чек-лист интеграции

  1. Показывайте сетьВсегда показывайте сеть рядом с монетой, например USDT в сети Tron. Отправка не в той сети может привести к потере средств.
  2. Показывайте мемоЕсли задан deposit.memo, депозит обязательно должен его содержать. Показывайте его так же заметно, как адрес.
  3. Объясняйте фиксированный курсОбмен по фиксированному курсу выплачивает заявленную сумму, только если пользователь отправит ровно from.amount до deposit.expires_at.
  4. Не раскрывайте ID заказовЛюбой, у кого есть ID, может просмотреть этот заказ. Не передавайте ID в аналитику, логи или публичные URL.
  5. Обрабатывайте ошибки по кодуВетвите логику по code, показывайте detail и соблюдайте Retry-After.
  6. Ссылайтесь на настоящий сайтСсылайтесь только на https://swapnoir.com. Никогда не запрашивайте у пользователей сид-фразы или приватные ключи.

История изменений

  • Выпущена v1. GET /currencies, GET /estimate, GET /orders/{id}, ошибки в формате RFC 9457, заголовки RateLimit и описание OpenAPI 3.1.

Поддержка

Есть вопросы, идеи или нужны повышенные лимиты для вашей интеграции? Напишите нам или свяжитесь с нами напрямую: info@swapnoir.com. Использование API регулируется нашими страницами «Условия» и «Конфиденциальность».

Последнее обновление: