API pública · v1 · Gratuita
API da Swapnoir
Cotações em tempo real, moedas aceitas e rastreamento de pedidos para sua carteira, bot ou site. Somente leitura, sem chave de API, sem conta.
- URL base
https://swapnoir.com/api/v1- Autenticação
- Nenhuma
- Formato
- JSON, UTF-8
- Erros
- RFC 9457
Visão geral
A API da Swapnoir oferece ao seu app os mesmos dados em tempo real usados pelo serviço de troca da swapnoir.com. É uma pequena API REST via HTTPS com três endpoints, que retorna JSON e é descrita em um arquivo OpenAPI 3.1 que você pode carregar no Postman, Insomnia, Scalar ou em um gerador de código.
Mostre cotações em tempo real
Widgets de preço, calculadoras e bots. As estimativas já incluem todas as taxas do pagamento.
Envie usuários para uma troca
Abra uma troca pré-preenchida em swapnoir.com a partir do seu app com um único link.
Rastrear pedidos
Acompanhe uma troca pelo ID do pedido e avise seus usuários quando ela for concluída.
Início rápido
Sem cadastro. Execute estes comandos em um terminal; cada um funciona de forma independente.
- Liste o que pode ser trocado. Use o
idde cada moeda nas outras chamadas.curl "https://swapnoir.com/api/v1/currencies" - Obtenha uma estimativa em tempo real. Quanto XMR você recebe por 0.01 BTC, já descontadas as taxas?
curl "https://swapnoir.com/api/v1/estimate?from=BTC&to=XMR&amount=0.01" - Envie seu usuário para a troca e acompanhe-a. O usuário conclui a troca em swapnoir.com e recebe uma página do pedido. Com o ID dela, você acompanha o pedido.
curl "https://swapnoir.com/api/v1/orders/K7M2QX9PRT4B"
Requisições e dados
| URL base | https://swapnoir.com/api/v1. Somente HTTPS. |
|---|---|
| Métodos | Todos os endpoints são GET. Os parâmetros vão na query string ou no caminho. |
| Respostas | application/json, UTF-8. Os erros usam application/problem+json. |
| Valores | Strings decimais como "0.01", para que não haja perda de precisão. Envie valores com ponto e no máximo decimals casas decimais da moeda. |
| IDs de moedas | Moeda mais rede, por exemplo BTC, USDT-TRC20. Nas requisições, não diferencia maiúsculas de minúsculas; nas respostas, vem sempre em maiúsculas. |
| Datas e horas | ISO 8601 em UTC, por exemplo 2026-10-05T12:00:00.000Z. |
| Navegadores | O CORS é aberto (Access-Control-Allow-Origin: *), então você pode chamar a API de uma página web. Nenhum cookie é usado. |
| Tor | Também disponível via Tor em http://swapnoqyyp3mfh3hoypzmvpnau7gymt7c32tybx2qew3s7sw7bzz7aqd.onion/api/v1, com os mesmos endpoints e limites. |
| Versionamento | A versão fica no caminho. Dentro da v1, só adicionamos coisas: novos endpoints, novos parâmetros opcionais, novos campos de resposta e novas moedas; por isso, ignore os campos que você não conhece. Qualquer mudança que quebraria uma integração é lançada como uma nova versão, e a v1 continua funcionando em paralelo. |
Autenticação
Nenhuma. Não há chaves de API, contas nem tokens, e as requisições não são vinculadas a ninguém. Nunca envie credenciais, frases-semente ou chaves privadas para a API; ela nunca vai pedi-las.
Limites de requisições
Os limites são contados por conexão, em uma janela móvel de um minuto.
| Endpoint | Requisições por minuto |
|---|---|
GET /currencies | 60 |
GET /estimate | 90 |
GET /orders/{id} | 30 |
Toda resposta traz os cabeçalhos padrão RateLimit-Policy (por exemplo 90;w=60) e RateLimit (por exemplo limit=90, remaining=89, reset=60). Acima do limite, você recebe 429 com um cabeçalho Retry-After em segundos.
- Armazene
/currenciesem cache por pelo menos 5 minutos; a lista raramente muda. - Enquanto o usuário digita um valor, espere cerca de meio segundo após a última tecla antes de pedir uma estimativa.
- Consulte um pedido no máximo a cada 10 segundos e pare quando
finalfortrue.
Erros
Os erros usam o formato padrão RFC 9457 problem details. Verifique o status HTTP e depois decida com base em code, que nunca muda. detail é uma mensagem em inglês simples que você pode mostrar ao seu usuário, e type aponta para a linha correspondente abaixo.
{
"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"
}| Código | HTTP | Significado |
|---|---|---|
invalid_parameter | 400 | Um parâmetro de consulta está ausente ou malformado. param indica qual. |
same_currency | 400 | from e to são a mesma moeda. |
receive_not_supported | 400 | A moeda to é só de envio (Lightning). |
amount_too_small | 422 | O valor está abaixo do mínimo para este par. min_amount contém o mínimo. |
pair_not_supported | 422 | Este par de moedas e redes não é oferecido. |
pair_unavailable | 503 | Não há cotação disponível para este par no momento. Tente mais tarde ou use outro valor. |
not_found | 404 | Não existe pedido com este ID, ou o pedido foi excluído. |
rate_limited | 429 | Você atingiu o limite de requisições. Aguarde o número de segundos indicado em Retry-After. |
internal_error | 500 | Algo deu errado do nosso lado. Tente mais tarde. |
Referência
Listar moedas
GET/api/v1/currencies
Todas as moedas e redes aceitas pela Swapnoir. Um token em outra rede é uma moeda diferente, por exemplo USDT-TRC20 e USDT-ERC20. A lista muda raramente; armazene-a em cache por alguns minutos.
O exemplo mostra três das moedas. Os campos da resposta abaixo são por moeda.
Requisição
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"]Resposta
{
"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"
}
]
}Campos da resposta
| Campo | Tipo | Descrição |
|---|---|---|
id | string | Moeda e rede. |
ticker | string | |
name | string | |
network | string | |
decimals | integer | Máximo de casas decimais aceitas nos valores. |
send | boolean | Pode ser usada como from. |
receive | boolean | Pode ser usada como to. |
memo | string or null | Nome do campo extra que algumas redes exigem junto com o endereço, como Destination tag; null quando não é usado. |
icon_url | string |
Obter uma estimativa
GET/api/v1/estimate
Quanto de to o usuário recebe por amount de from, com todas as taxas de troca e de rede do pagamento já incluídas. As estimativas são em tempo real e não ficam reservadas: o valor final é definido quando a troca é criada (taxa fixa) ou quando o depósito é confirmado (taxa flutuante).
Parâmetros
| Nome | Local | Descrição |
|---|---|---|
fromobrigatório | query | Moeda que o usuário envia. Exemplo: BTC. |
toobrigatório | query | Moeda que o usuário recebe. BTC-LN é só de envio. Exemplo: XMR. |
amountobrigatório | query | Valor de from, em formato decimal com ponto e no máximo decimals casas decimais da moeda. Exemplo: 0.01. |
rate | query | float (padrão) acompanha o mercado até o depósito ser confirmado. fixed trava o valor quando a troca é criada. Um de float, fixed. Exemplo: float. |
Requisição
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"])Resposta
{
"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"
}Campos da resposta
| Campo | Tipo | Descrição |
|---|---|---|
from | string | Moeda e rede. |
to | string | Qualquer moeda, exceto as que são só de envio. |
rate_type | string | Tipo de taxa |
amount_from | string | O valor consultado. |
amount_to | string | O que o usuário recebe, após todas as taxas. |
rate | string | Valor de to por 1 from, após as taxas. |
usd_value | string or null | Valor aproximado de amount_from em dólares americanos, quando conhecido. |
quoted_at | string |
Obter um pedido
GET/api/v1/orders/{id}
Status em tempo real e detalhes de uma troca. O ID do pedido é a última parte da URL da página do pedido. Qualquer pessoa com o ID pode ver o pedido, então trate-o como uma senha. Consulte no máximo a cada 10 segundos e pare quando final for true. Os pedidos são excluídos 7 dias após serem finalizados.
Parâmetros
| Nome | Local | Descrição |
|---|---|---|
idobrigatório | path | ID do pedido, por exemplo K7M2QX9PRT4B. |
Requisição
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)Resposta
{
"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"
}Campos da resposta
| Campo | Tipo | Descrição |
|---|---|---|
id | string | ID do pedido |
status | string | Status do pedido |
final | boolean | True para done, expired, refunded e failed: pare de consultar. |
rate_type | string | Tipo de taxa |
created_at | string | |
updated_at | string | |
from | object | |
from.currency | string | Moeda e rede. |
from.amount | string | Valor a depositar. |
to | object | |
to.currency | string | Moeda e rede. |
to.amount | string or null | Pagamento estimado, ou o pagamento final quando amount_is_final for true. |
to.amount_is_final | boolean | |
deposit | object | |
deposit.address | string or null | Para onde o usuário envia o depósito; null enquanto o status for preparing. |
deposit.memo | string or null | Memo ou tag de destino que deve ser incluído no depósito, quando definido. |
deposit.expires_at | string or null | Envie antes deste horário, quando definido. |
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 | Link do explorador de blocos, quando houver. |
transactions.payout | null or object | |
transactions.payout.hash | string | |
transactions.payout.url | string or null | Link do explorador de blocos, quando houver. |
links | object | |
links.order_page | string | |
links.receipt | string |
Guias
Criar uma troca
As trocas são criadas em swapnoir.com, assim seu usuário sempre recebe a própria página do pedido e mantém o controle dela. Seu app envia o usuário para lá com as moedas e o valor já preenchidos:
| Link | Abre |
|---|---|
https://swapnoir.com/exchange?from=BTC&to=XMR&amount=0.01&rate=float | A troca na etapa do endereço, com a estimativa em tempo real exibida. Ideal para botões “Trocar agora”. |
https://swapnoir.com/?from=BTC&to=XMR&amount=0.01 | A página inicial com o formulário de troca preenchido, para que o usuário ainda possa alterar as moedas e o valor. |
Ambos aceitam os mesmos from, to, amount e rate opcional que Obter uma estimativa. Para abrir a página em outro idioma, coloque o código do idioma no início, por exemplo /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>- O usuário cola o endereço de recebimento e, opcionalmente, um endereço de reembolso, passa por uma rápida verificação de segurança e clica em Trocar agora.
- O usuário chega à página do pedido,
https://swapnoir.com/order/<ID>, com o endereço de depósito e o valor. - Se o seu app precisar acompanhar o pedido, peça ao usuário para colar o link ou o ID do pedido e depois consulte Obter um pedido periodicamente.
Status dos pedidos
Uma troca normal passa por awaiting → confirming → exchanging → sending → done. Mostre o status ao seu usuário com suas próprias palavras e pare de consultar quando final for true.
| Status | Final | Significado |
|---|---|---|
preparing | Não | O endereço de depósito está sendo preparado. Ele costuma aparecer em poucos minutos. |
awaiting | Não | Aguardando o depósito. Envie somente enquanto o pedido estiver neste status e antes de deposit.expires_at. |
confirming | Não | O depósito foi detectado e está aguardando confirmações da rede. |
exchanging | Não | O depósito foi confirmado e está sendo trocado. |
sending | Não | As moedas trocadas estão sendo enviadas para o endereço de recebimento. |
processing | Não | Em andamento. Usado quando não se conhece um status mais específico. |
done | Sim | Concluída. O pagamento foi enviado; veja transactions.payout. |
expired | Sim | Nenhum depósito chegou dentro do prazo. Um depósito atrasado ainda pode ser concluído ou reembolsado pelo suporte. |
hold | Não | Pausado para uma análise de rotina. O usuário deve falar com o suporte e informar o ID do pedido. |
attention | Não | Algo precisa ser verificado, por exemplo um depósito com valor errado. O usuário deve falar com o suporte. |
refunding | Não | O depósito está sendo devolvido para o endereço de reembolso. |
refunded | Sim | O depósito foi devolvido. |
failed | Sim | Não foi possível concluir a troca. O usuário deve falar com o suporte. |
Moedas aceitas
A mesma lista retornada por Listar moedas. Novas moedas são adicionadas com o tempo, então leia a lista pela API em vez de fixá-la no código.
| ID | Moeda | Rede | Casas decimais | Recebimento | Memo |
|---|---|---|---|---|---|
BTC | Bitcoin | 8 | Sim | – | |
XMR | Monero | 12 | Sim | – | |
ETH | Ethereum | 8 | Sim | – | |
USDT-TRC20 | Tron (TRC20) | 6 | Sim | – | |
USDT-ERC20 | Ethereum (ERC20) | 6 | Sim | – | |
USDT-SOL | Solana | 6 | Sim | – | |
USDC-ERC20 | Ethereum (ERC20) | 6 | Sim | – | |
LTC | Litecoin | 8 | Sim | – | |
SOL | Solana | 9 | Sim | – | |
BTC-LN | Lightning | 8 | Só envio | – | |
TRX | Tron | 6 | Sim | – | |
BNB | BNB Smart Chain (BEP20) | 8 | Sim | – | |
DOGE | Dogecoin | 8 | Sim | – | |
ZEC | Zcash | 8 | Sim | – | |
BCH | Bitcoin Cash | 8 | Sim | – | |
DASH | Dash | 8 | Sim | – | |
XRP | XRP Ledger | 6 | Sim | Tag de destino |
Checklist de integração
- Mostre a redeMostre sempre a rede ao lado da moeda, por exemplo USDT na Tron. Enviar pela rede errada pode causar perda de fundos.
- Mostre o memoQuando
deposit.memoestiver definido, o depósito precisa incluí-lo. Exiba-o com o mesmo destaque do endereço. - Explique a taxa fixaUma troca com taxa fixa paga o valor cotado somente se o usuário enviar exatamente
from.amountantes dedeposit.expires_at. - Mantenha os IDs de pedidos privadosQualquer pessoa com um ID pode ver esse pedido. Não coloque IDs em ferramentas de análise, logs ou URLs públicas.
- Trate os erros pelo códigoDecida com base em
code, mostredetaile respeiteRetry-After. - Crie links para o site verdadeiroUse links apenas para https://swapnoir.com. Nunca peça aos usuários frases-semente ou chaves privadas.
Histórico de alterações
- v1 lançada.
GET /currencies,GET /estimate,GET /orders/{id}, erros RFC 9457, cabeçalhosRateLimite a descrição OpenAPI 3.1.
Suporte
Dúvidas, ideias ou limites maiores para sua integração: envie uma mensagem ou fale conosco em info@swapnoir.com. O uso da API é regido pelas nossas páginas de Termos e Privacidade.
Última atualização: .