Swapnoir
ES

API pública · v1 · Gratis

API de Swapnoir

Tasas de cambio en tiempo real, monedas admitidas y seguimiento de órdenes para tu billetera, bot o sitio web. Solo lectura, sin clave de API y sin cuenta.

URL base
https://swapnoir.com/api/v1
Autenticación
Ninguna
Formato
JSON, UTF-8
Errores
RFC 9457

Descripción general

La API de Swapnoir le da a tu app los mismos datos en tiempo real que usa la plataforma de intercambio de swapnoir.com. Es una pequeña API REST sobre HTTPS con tres endpoints, devuelve JSON y está descrita en un archivo OpenAPI 3.1 que puedes cargar en Postman, Insomnia, Scalar o un generador de código.

Muestra tasas en tiempo real

Widgets de precios, calculadoras y bots. Las estimaciones ya incluyen todas las comisiones del pago.

Envía usuarios a un intercambio

Abre desde tu app un intercambio ya preparado en swapnoir.com con un solo enlace.

Sigue órdenes

Sigue un intercambio por su ID de orden y avisa a tus usuarios cuando se complete.

Inicio rápido

No necesitas registrarte. Ejecuta estos comandos en una terminal; cada uno funciona por sí solo.

  1. Consulta lo que puedes intercambiar. Usa el id de cada moneda en las demás llamadas.
    curl "https://swapnoir.com/api/v1/currencies"
  2. Obtén una estimación en tiempo real. ¿Cuánto XMR obtienes con 0.01 BTC, después de comisiones?
    curl "https://swapnoir.com/api/v1/estimate?from=BTC&to=XMR&amount=0.01"
  3. Envía a tu usuario al intercambio y síguelo. El usuario termina en swapnoir.com y obtiene una página de la orden. Su ID te permite seguir la orden.
    curl "https://swapnoir.com/api/v1/orders/K7M2QX9PRT4B"

Pruébalo en vivo

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

Solicitudes y datos

URL basehttps://swapnoir.com/api/v1. Solo HTTPS.
MétodosTodos los endpoints son GET. Los parámetros van en la cadena de consulta o en la ruta.
Respuestasapplication/json, UTF-8. Los errores usan application/problem+json.
CantidadesCadenas decimales como "0.01", para no perder precisión. Envía las cantidades con punto y como máximo los decimals de la moneda.
ID de monedaMoneda más red, por ejemplo BTC, USDT-TRC20. En las solicitudes no se distingue entre mayúsculas y minúsculas; en las respuestas, siempre en mayúsculas.
Fechas y horasISO 8601 en UTC, por ejemplo 2026-10-05T12:00:00.000Z.
NavegadoresCORS está abierto (Access-Control-Allow-Origin: *), así que puedes llamar a la API desde una página web. No se usan cookies.
TorTambién disponible a través de Tor en http://swapnoqyyp3mfh3hoypzmvpnau7gymt7c32tybx2qew3s7sw7bzz7aqd.onion/api/v1, con los mismos endpoints y límites.
Control de versionesLa versión va en la ruta. Dentro de v1 solo añadimos cosas: nuevos endpoints, nuevos parámetros opcionales, nuevos campos de respuesta y nuevas monedas, así que ignora los campos que no conozcas. Cualquier cambio que rompa una integración se publica como una versión nueva, y v1 sigue funcionando en paralelo.

Autenticación

Ninguna. No hay claves de API, cuentas ni tokens, y las solicitudes no se vinculan a nadie. Nunca envíes credenciales, frases semilla ni claves privadas a la API; nunca te las pedirá.

Límites de solicitudes

Los límites se cuentan por conexión en una ventana móvil de un minuto.

EndpointSolicitudes por minuto
GET /currencies60
GET /estimate90
GET /orders/{id}30

Cada respuesta incluye las cabeceras estándar RateLimit-Policy (por ejemplo 90;w=60) y RateLimit (por ejemplo limit=90, remaining=89, reset=60). Si superas el límite, recibes un 429 con una cabecera Retry-After en segundos.

  • Guarda /currencies en caché durante al menos 5 minutos; cambia muy poco.
  • Mientras el usuario escribe una cantidad, espera aproximadamente medio segundo tras la última pulsación antes de pedir una estimación.
  • Consulta una orden como máximo cada 10 segundos y deja de hacerlo cuando final sea true.

Errores

Los errores usan el formato estándar RFC 9457 problem details. Comprueba el estado HTTP y luego decide según code, que nunca cambia. detail es un mensaje sencillo en inglés que puedes mostrar a tu usuario, y type enlaza con la fila correspondiente de la tabla de abajo.

422 Ejemplo
{
  "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ódigoHTTPSignificado
invalid_parameter400Falta un parámetro de consulta o tiene un formato incorrecto. param indica cuál.
same_currency400from y to son la misma moneda.
receive_not_supported400La moneda to es solo de envío (Lightning).
amount_too_small422La cantidad está por debajo del mínimo para este par. min_amount contiene el mínimo.
pair_not_supported422Este par de monedas y redes no se ofrece.
pair_unavailable503Ahora mismo no hay ninguna tasa disponible para este par. Vuelve a intentarlo más tarde o prueba con otra cantidad.
not_found404No hay ninguna orden con este ID, o la orden se ha eliminado.
rate_limited429Has alcanzado el límite de solicitudes. Espera el número de segundos indicado en Retry-After.
internal_error500Algo salió mal por nuestra parte. Vuelve a intentarlo más tarde.

Referencia

Listar monedas

GET/api/v1/currencies

Todas las monedas y redes que admite Swapnoir. Un token en otra red es una moneda distinta, por ejemplo USDT-TRC20 y USDT-ERC20. La lista cambia muy poco; guárdala en caché unos minutos.

El ejemplo muestra tres de las monedas. Los campos de respuesta de abajo son por moneda.

Solicitud

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"]

Respuesta

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"
    }
  ]
}
Campos de la respuesta
CampoTipoDescripción
idstringMoneda y red.
tickerstring
namestring
networkstring
decimalsintegerNúmero máximo de decimales admitidos en las cantidades.
sendbooleanSe puede usar como from.
receivebooleanSe puede usar como to.
memostring or nullNombre del campo adicional que algunas redes requieren junto con la dirección, como Destination tag; null cuando no se usa.
icon_urlstring

Obtener una estimación

GET/api/v1/estimate

Cuánto to recibe el usuario por amount de from, con todas las comisiones de intercambio y de red del pago ya incluidas. Las estimaciones son en tiempo real y no se reservan: la cantidad final se fija al crear el intercambio (tasa fija) o al confirmarse el depósito (tasa flotante).

Parámetros

NombreUbicaciónDescripción
fromobligatorioqueryMoneda que envía el usuario. Ejemplo: BTC.
toobligatorioqueryMoneda que recibe el usuario. BTC-LN es solo de envío. Ejemplo: XMR.
amountobligatorioqueryCantidad de from, como número decimal con punto y como máximo los decimals de la moneda. Ejemplo: 0.01.
ratequeryfloat (predeterminado) sigue el mercado hasta que se confirma el depósito. fixed bloquea la cantidad al crear el intercambio. Uno de estos valores: float, fixed. Ejemplo: float.

Solicitud

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"])

Respuesta

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 Por debajo del mínimo
{
  "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 Parámetro no válido
{
  "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 de la respuesta
CampoTipoDescripción
fromstringMoneda y red.
tostringCualquier moneda, excepto las que son solo de envío.
rate_typestringTipo de tasa
amount_fromstringLa cantidad que consultaste.
amount_tostringLo que recibe el usuario, después de todas las comisiones.
ratestringCantidad de to por cada 1 from, después de comisiones.
usd_valuestring or nullValor aproximado en dólares estadounidenses de amount_from, cuando se conoce.
quoted_atstring

Obtener una orden

GET/api/v1/orders/{id}

Estado en tiempo real y detalles de un intercambio. El ID de orden es la última parte de la URL de la página de la orden. Cualquiera que tenga el ID puede ver la orden, así que trátalo como una contraseña. Consulta como máximo cada 10 segundos y deja de hacerlo cuando final sea true. Las órdenes se eliminan 7 días después de finalizar.

Parámetros

NombreUbicaciónDescripción
idobligatoriopathID de orden, por ejemplo K7M2QX9PRT4B.

Solicitud

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)

Respuesta

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 No encontrado
{
  "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 de la respuesta
CampoTipoDescripción
idstringID de orden
statusstringEstado de la orden
finalbooleanEs true para done, expired, refunded y failed: deja de consultar.
rate_typestringTipo de tasa
created_atstring
updated_atstring
fromobject
from.currencystringMoneda y red.
from.amountstringCantidad que hay que depositar.
toobject
to.currencystringMoneda y red.
to.amountstring or nullPago estimado, o el pago final cuando amount_is_final es true.
to.amount_is_finalboolean
depositobject
deposit.addressstring or nullDirección a la que el usuario envía el depósito; null mientras el estado es preparing.
deposit.memostring or nullMemo o etiqueta de destino que debe incluirse con el depósito, si se indica.
deposit.expires_atstring or nullEnviar antes de este momento, si se indica.
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 nullEnlace al explorador de bloques, cuando se conoce.
transactions.payoutnull or object
transactions.payout.hashstring
transactions.payout.urlstring or nullEnlace al explorador de bloques, cuando se conoce.
linksobject
links.order_pagestring
links.receiptstring

Guías

Crear un intercambio

Los intercambios se crean en swapnoir.com, así que tu usuario siempre obtiene su propia página de la orden y mantiene el control sobre ella. Tu app envía al usuario allí con las monedas y la cantidad ya indicadas:

EnlaceQué abre
https://swapnoir.com/exchange?from=BTC&to=XMR&amount=0.01&rate=floatEl intercambio en el paso de la dirección, con la estimación en tiempo real visible. Ideal para botones «Intercambiar ya».
https://swapnoir.com/?from=BTC&to=XMR&amount=0.01La página de inicio con el cuadro de intercambio ya completado, para que el usuario aún pueda cambiar las monedas y la cantidad.

Ambos aceptan los mismos from, to, amount y rate opcional que Obtener una estimación. Para abrir la página en otro idioma, pon primero el código de idioma, por ejemplo /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. El usuario pega su dirección de recepción y, si quiere, una dirección de reembolso, supera una breve verificación de seguridad y pulsa Intercambiar ya.
  2. Llega a la página de su orden, https://swapnoir.com/order/<ID>, con la dirección de depósito y la cantidad.
  3. Si tu app debe seguir la orden, pide al usuario que pegue el enlace o el ID de la orden y luego consulta periódicamente Obtener una orden.

Estados de la orden

Un intercambio normal pasa por awaiting → confirming → exchanging → sending → done. Muestra status a tu usuario con tus propias palabras y deja de consultar cuando final sea true.

EstadoFinalSignificado
preparingNoSe está preparando la dirección de depósito. Suele aparecer en pocos minutos.
awaitingNoEsperando el depósito. Envía solo mientras la orden esté en este estado y antes de deposit.expires_at.
confirmingNoSe detectó el depósito y está a la espera de confirmaciones de la red.
exchangingNoEl depósito está confirmado y se está intercambiando.
sendingNoLas monedas intercambiadas se están enviando a la dirección de recepción.
processingNoEn curso. Se usa cuando no se conoce un estado más concreto.
doneSíCompletado. Se envió el pago; consulta transactions.payout.
expiredSíNo llegó ningún depósito a tiempo. Un depósito tardío aún puede completarse o reembolsarse a través de soporte.
holdNoEn pausa para una revisión rutinaria. El usuario debe contactar con soporte e indicar el ID de orden.
attentionNoHay algo que revisar, por ejemplo un depósito con una cantidad incorrecta. El usuario debe contactar con soporte.
refundingNoEl depósito se está devolviendo a la dirección de reembolso.
refundedSíEl depósito se devolvió.
failedSíNo se pudo completar el intercambio. El usuario debe contactar con soporte.

Monedas admitidas

La misma lista que devuelve Listar monedas. Con el tiempo se añaden monedas nuevas, así que lee la lista desde la API en lugar de escribirla en el código.

IDMonedaRedDecimalesRecibirMemo
BTCBitcoinBitcoin8Sí–
XMRMoneroMonero12Sí–
ETHEthereumEthereum8Sí–
USDT-TRC20TetherTron (TRC20)6Sí–
USDT-ERC20TetherEthereum (ERC20)6Sí–
USDT-SOLTetherSolana6Sí–
USDC-ERC20USD CoinEthereum (ERC20)6Sí–
LTCLitecoinLitecoin8Sí–
SOLSolanaSolana9Sí–
BTC-LNBitcoin LightningLightning8Solo envío–
TRXTronTron6Sí–
BNBBNBBNB Smart Chain (BEP20)8Sí–
DOGEDogecoinDogecoin8Sí–
ZECZcashZcash8Sí–
BCHBitcoin CashBitcoin Cash8Sí–
DASHDashDash8Sí–
XRPXRPXRP Ledger6SíEtiqueta de destino

Lista de comprobación para la integración

  1. Muestra la redMuestra siempre la red junto a la moneda, p. ej., USDT en Tron. Un envío por la red equivocada puede suponer la pérdida de los fondos.
  2. Muestra el memoCuando deposit.memo tiene valor, el depósito debe incluirlo. Muéstralo con la misma claridad que la dirección.
  3. Explica la tasa fijaUn intercambio con tasa fija paga la cantidad cotizada solo si el usuario envía exactamente from.amount antes de deposit.expires_at.
  4. Mantén privados los ID de ordenCualquiera que tenga un ID puede ver esa orden. No incluyas los ID en analíticas, registros ni URL públicas.
  5. Gestiona los errores por códigoDecide según code, muestra detail y respeta Retry-After.
  6. Enlaza al sitio auténticoEnlaza solo a https://swapnoir.com. Nunca pidas a los usuarios frases semilla ni claves privadas.

Registro de cambios

  • v1 publicada. GET /currencies, GET /estimate, GET /orders/{id}, errores RFC 9457, cabeceras RateLimit y la descripción OpenAPI 3.1.

Soporte

Preguntas, ideas o límites más altos para tu integración: envíanos un mensaje o escríbenos a info@swapnoir.com. El uso de la API se rige por nuestras páginas de Términos y Privacidad.

Última actualización: .