Публичный 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 заказа и уведомляйте пользователей о его завершении.
Быстрый старт
Регистрация не нужна. Выполните эти команды в терминале; каждая работает сама по себе.
- Получите список доступных валют. Используйте
idкаждой валюты в остальных запросах.curl "https://swapnoir.com/api/v1/currencies" - Получите актуальную оценку. Сколько XMR можно получить за 0.01 BTC с учётом комиссий?
curl "https://swapnoir.com/api/v1/estimate?from=BTC&to=XMR&amount=0.01" - Направьте пользователя к обмену и отслеживайте его. Пользователь завершает оформление на swapnoir.com и получает страницу заказа. По ID заказа вы сможете следить за ним.
curl "https://swapnoir.com/api/v1/orders/K7M2QX9PRT4B"
Запросы и данные
| Базовый URL | https://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 /currencies | 60 |
GET /estimate | 90 |
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 ссылается на соответствующую строку таблицы ниже.
{
"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_parameter | 400 | Параметр запроса отсутствует или имеет неверный формат. Его имя указано в param. |
same_currency | 400 | from и to — одна и та же валюта. |
receive_not_supported | 400 | Валюта to доступна только для отправки (Lightning). |
amount_too_small | 422 | Сумма ниже минимума для этой пары. Минимум указан в min_amount. |
pair_not_supported | 422 | Эта пара валют и сетей не поддерживается. |
pair_unavailable | 503 | Для этой пары сейчас нет доступного курса. Повторите позже или попробуйте другую сумму. |
not_found | 404 | Заказа с этим ID не существует, или заказ был удалён. |
rate_limited | 429 | Вы достигли лимита запросов. Подождите столько секунд, сколько указано в Retry-After. |
internal_error | 500 | На нашей стороне что-то пошло не так. Повторите позже. |
Справочник
Список валют
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"]Ответ
{
"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"
}
]
}Поля ответа
| Поле | Тип | Описание |
|---|---|---|
id | string | Валюта и сеть. |
ticker | string | |
name | string | |
network | string | |
decimals | integer | Максимальное число знаков после точки в суммах. |
send | boolean | Можно использовать как from. |
receive | boolean | Можно использовать как to. |
memo | string or null | Название дополнительного поля, которое в некоторых сетях требуется вместе с адресом, например Destination tag; null, если не используется. |
icon_url | string |
Получить оценку
GET/api/v1/estimate
Сколько to получит пользователь за amount в from, с уже учтёнными комиссиями за обмен и комиссиями сети за выплату. Оценки рассчитываются в реальном времени и не резервируются: итоговая сумма фиксируется при создании обмена (фиксированный курс) или при подтверждении депозита (плавающий курс).
Параметры
| Имя | Где | Описание |
|---|---|---|
fromобязательно | query | Валюта, которую отправляет пользователь. Пример: BTC. |
toобязательно | query | Валюта, которую получает пользователь. BTC-LN — только для отправки. Пример: XMR. |
amountобязательно | query | Сумма в from: десятичное число с точкой, знаков после точки — не больше, чем decimals у этой валюты. Пример: 0.01. |
rate | query | float (по умолчанию) следует за рынком до подтверждения депозита. 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"])Ответ
{
"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"
}{
"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"
}{
"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"
}Поля ответа
| Поле | Тип | Описание |
|---|---|---|
from | string | Валюта и сеть. |
to | string | Любая валюта, кроме доступных только для отправки. |
rate_type | string | Тип курса |
amount_from | string | Сумма из запроса. |
amount_to | string | Сумма, которую получит пользователь после всех комиссий. |
rate | string | Количество to за 1 from после вычета комиссий. |
usd_value | string or null | Примерная стоимость amount_from в долларах США, если известна. |
quoted_at | string |
Получить заказ
GET/api/v1/orders/{id}
Текущий статус и детали обмена. ID заказа — последняя часть URL страницы заказа. Любой, у кого есть ID, может просмотреть заказ, поэтому обращайтесь с ним как с паролем. Опрашивайте не чаще раза в 10 секунд и прекращайте, когда final равно true. Заказы удаляются через 7 дней после завершения.
Параметры
| Имя | Где | Описание |
|---|---|---|
idобязательно | path | ID заказа, например 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)Ответ
{
"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"
}
}{
"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"
}Поля ответа
| Поле | Тип | Описание |
|---|---|---|
id | string | ID заказа |
status | string | Статус заказа |
final | boolean | Равно true для done, expired, refunded и failed: прекратите опрос. |
rate_type | string | Тип курса |
created_at | string | |
updated_at | string | |
from | object | |
from.currency | string | Валюта и сеть. |
from.amount | string | Сумма депозита. |
to | object | |
to.currency | string | Валюта и сеть. |
to.amount | string or null | Ожидаемая выплата или итоговая выплата, когда amount_is_final равно true. |
to.amount_is_final | boolean | |
deposit | object | |
deposit.address | string or null | Куда пользователь отправляет депозит; null, пока статус preparing. |
deposit.memo | string or null | Мемо или тег назначения, который нужно указать при отправке депозита, если он задан. |
deposit.expires_at | string or null | Отправить депозит нужно до этого времени, если оно задано. |
payout | object | |
payout.address | string | |
payout.memo | string or null | |
refund | null or object | |
refund.address | string | |
refund.memo | string or null | |
transactions | object | |
transactions.deposit | null or object | |
transactions.deposit.hash | string | |
transactions.deposit.url | string or null | Ссылка на обозреватель блоков, если она известна. |
transactions.payout | null or object | |
transactions.payout.hash | string | |
transactions.payout.url | string or null | Ссылка на обозреватель блоков, если она известна. |
links | object | |
links.order_page | string | |
links.receipt | string |
Руководства
Создание обмена
Обмены создаются на 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>- Пользователь вставляет адрес получения и, при желании, адрес для возврата, проходит быструю проверку безопасности и нажимает Начать обмен.
- Пользователь попадает на страницу своего заказа,
https://swapnoir.com/order/<ID>, с адресом для депозита и суммой. - Если ваше приложение должно отслеживать заказ, попросите пользователя вставить ссылку на заказ или его 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 | Валюта | Сеть | Знаков после точки | Получение | Мемо |
|---|---|---|---|---|---|
BTC | Bitcoin | 8 | Да | – | |
XMR | Monero | 12 | Да | – | |
ETH | Ethereum | 8 | Да | – | |
USDT-TRC20 | Tron (TRC20) | 6 | Да | – | |
USDT-ERC20 | Ethereum (ERC20) | 6 | Да | – | |
USDT-SOL | Solana | 6 | Да | – | |
USDC-ERC20 | Ethereum (ERC20) | 6 | Да | – | |
LTC | Litecoin | 8 | Да | – | |
SOL | Solana | 9 | Да | – | |
BTC-LN | Lightning | 8 | Только отправка | – | |
TRX | Tron | 6 | Да | – | |
BNB | BNB Smart Chain (BEP20) | 8 | Да | – | |
DOGE | Dogecoin | 8 | Да | – | |
ZEC | Zcash | 8 | Да | – | |
BCH | Bitcoin Cash | 8 | Да | – | |
DASH | Dash | 8 | Да | – | |
XRP | XRP Ledger | 6 | Да | Тег назначения |
Чек-лист интеграции
- Показывайте сетьВсегда показывайте сеть рядом с монетой, например USDT в сети Tron. Отправка не в той сети может привести к потере средств.
- Показывайте мемоЕсли задан
deposit.memo, депозит обязательно должен его содержать. Показывайте его так же заметно, как адрес. - Объясняйте фиксированный курсОбмен по фиксированному курсу выплачивает заявленную сумму, только если пользователь отправит ровно
from.amountдоdeposit.expires_at. - Не раскрывайте ID заказовЛюбой, у кого есть ID, может просмотреть этот заказ. Не передавайте ID в аналитику, логи или публичные URL.
- Обрабатывайте ошибки по кодуВетвите логику по
code, показывайтеdetailи соблюдайтеRetry-After. - Ссылайтесь на настоящий сайтСсылайтесь только на https://swapnoir.com. Никогда не запрашивайте у пользователей сид-фразы или приватные ключи.
История изменений
- Выпущена v1.
GET /currencies,GET /estimate,GET /orders/{id}, ошибки в формате RFC 9457, заголовкиRateLimitи описание OpenAPI 3.1.
Поддержка
Есть вопросы, идеи или нужны повышенные лимиты для вашей интеграции? Напишите нам или свяжитесь с нами напрямую: info@swapnoir.com. Использование API регулируется нашими страницами «Условия» и «Конфиденциальность».
Последнее обновление: