El árbol del catálogo

Recorre el catálogo con un nivel acotado por llamada (plataformas, luego países, luego proveedores, luego opciones) sin clave de API, y usa los ids directamente en un pedido.

Insertar
Vista previa de la tarjeta
<a href="https://numestri.com/docs/es/the-catalogue-tree"><img src="https://numestri.com/docs/_api/public/orgs/25229885-9620-4c08-bd2e-a0d0d74ac8b6/spaces/ef21e0c3-966d-4b03-b6d2-e66d449835d4/pages/3110162f-a6e2-4b2b-8fa0-d3638b0fd9f9/social-card.svg?v=3e7ae33eec8b" alt="El árbol del catálogo" width="600" height="315"></a>

El catálogo es un árbol. Cada llamada devuelve solo el nivel que hay debajo de la elección que hiciste, así que nunca descargas todo el mercado para encontrar un precio.

/catalog/platforms                                                         todas las plataformas con stock
/catalog/platforms/{platform}/countries                                    dónde se vende esa plataforma
/catalog/platforms/{platform}/countries/{country}/providers                quién la vende allí
/catalog/platforms/{platform}/countries/{country}/providers/{provider}/options   desde qué la vende cada uno

Cada id del recorrido es exacto y es lo que acepta /purchase/sms.

No necesitas clave

Todo el árbol es público. Si lo llamas sin clave, recibes los precios de lista públicos, con un límite de 10 solicitudes por segundo por dirección IP. Si envías tu clave, cada precio es el de tu cuenta (lo que realmente te cobrará un pedido), con el límite de tu cuenta. Una clave incorrecta se rechaza con 403 en lugar de ignorarse. Consulta Autenticación.

curl https://numestri.com/api/v1/catalog/platforms
{
  "success": 1,
  "prices_at": "2026-10-14T01:40:00.000Z",
  "count": 1326,
  "next": "/api/v1/catalog/platforms/{platform}/countries",
  "data": [
    { "id": "discord", "name": "Discord", "countries": 12, "from_price": "0.07", "from_price_cents": 7 }
  ]
}

Campo

Significado

id

El id de la plataforma: {platform} en la siguiente ruta, service en un pedido.

countries

En cuántos países tiene stock.

from_price / from_price_cents

Su número más barato, en cualquier país.

Ids: plataforma, país, proveedor, opción

Id

Aspecto

¿Estable?

Úsalo como

Plataforma

telegram, whatsapp

Sí

service

País

US, GB (en mayúsculas)

Sí

country

Proveedor

prv_ + 10 caracteres, p. ej. prv_k3Jd9QmXa2

Sí: un mismo proveedor conserva su identificador en todas las plataformas, países y a lo largo del tiempo

provider

Opción

De 8 a 32 letras, dígitos, - o _, p. ej. k3Jd9QmXa2Lp0cWe

Mientras exista esa oferta

option

Ambos identificadores son opacos. El de un proveedor no dice nada de quién está detrás, y el id de una opción es propio de una plataforma y un país (la misma oferta en otro lugar tiene otro id), así que no los analices ni los construyas tú: cópialos del catálogo. Una opción que ya no existe se rechaza al hacer el pedido con el código OPTION_GONE.

Reglas que conviene conocer

  • Solo lo que tiene stock. Cada nivel muestra únicamente lo que puedes comprar ahora mismo. Una elección sin nada debajo devuelve un 404 cuyo mensaje te remite al nivel superior:

    { "success": 0, "errors": [{ "message": "Nothing is in stock for \"discord\" in \"FR\". See /api/v1/catalog/platforms/discord/countries.", "param": "country" }] }
  • Ids exactos. Telegram, tg, us y United States no son ids. En una ruta del catálogo no encuentran nada y responden 404; como parámetro service o country de /request/price o /purchase/sms se rechazan con 400. Usa telegram y US tal como aparecen en el catálogo.

  • Actualizado. Los precios y el stock se actualizan aproximadamente cada dos minutos; prices_at indica cuándo se leyeron los precios que estás viendo.

  • En arranque. Justo después de un reinicio, el catálogo puede responder 503 con Prices are being refreshed. Try again in a few seconds.: vuelve a intentarlo en un momento.

  • Los números compartidos no están en el árbol. El árbol muestra números privados. Si hay un número compartido más barato, con bandeja pública, para una plataforma y un país, lo indica el campo shared_inbox de /request/price.

Caché con ETags

Cada nivel incluye un ETag y Cache-Control: private, max-age=30. Devuelve el ETag como If-None-Match y, mientras nada haya cambiado en ese nivel, recibirás un 304 sin cuerpo en lugar de la lista:

curl -i https://numestri.com/api/v1/catalog/platforms/discord/countries
# HTTP/1.1 200 OK
# ETag: W/"…"

curl -i https://numestri.com/api/v1/catalog/platforms/discord/countries -H 'If-None-Match: W/"…"'
# HTTP/1.1 304 Not Modified
  • Las etiquetas son débiles y se comparan de forma débil: W/"x" y "x" coinciden. If-None-Match puede contener una lista separada por comas, o *.

  • La etiqueta cambia cada vez que pueden haber cambiado los precios que hay detrás del nivel (también cuando cambian los precios que se te aplican a ti), así que un 304 siempre significa que tu copia está al día.

  • Los precios públicos y los de tu cuenta pueden tener etiquetas distintas. Guarda cada etiqueta con la respuesta de la que salió y no reutilices una etiqueta anónima en una solicitud con clave.

  • Una solicitud con key= en la URL nunca se puede almacenar en caché; envía la clave en una cabecera si quieres caché.

Llamada de resumen

GET /api/v1/catalog describe el árbol y las tres formas de hacer un pedido, para que un cliente pueda descubrirlo sin rutas escritas a mano. También es pública.

{
  "success": 1,
  "prices_at": "2026-10-14T01:40:00.000Z",
  "platforms_in_stock": 1326,
  "tree": [
    { "level": 1, "list": "platforms", "path": "/api/v1/catalog/platforms" },
    { "level": 2, "list": "countries for a platform", "path": "/api/v1/catalog/platforms/{platform}/countries" },
    { "level": 3, "list": "providers for a platform in a country", "path": "/api/v1/catalog/platforms/{platform}/countries/{country}/providers" },
    { "level": 4, "list": "a provider's options", "path": "/api/v1/catalog/platforms/{platform}/countries/{country}/providers/{provider}/options" }
  ],
  "ordering": {
    "endpoint": "/api/v1/purchase/sms",
    "choose_by": [
      "service + country: the best option, failing over to the next",
      "service + country + provider: that provider only, its best option first",
      "service + country + option: exactly that option at its listed price, or nothing"
    ]
  }
}

Listas públicas más sencillas

Si solo necesitas nombres e ids (para una lista desplegable, por ejemplo), hay dos listas planas que mantienen el formato que usan la mayoría de las API de verificación. No aceptan ninguna clave.

Endpoint

Devuelve

GET /service/retrieve_all[?country=US]

[{ "ID": "telegram", "name": "Telegram", "from_price": "0.99" }]

GET /country/retrieve_all

[{ "ID": "US", "name": "United States", "short_name": "US" }]

ID es el id exacto que aceptan los endpoints de pedidos. Ambas muestran siempre los precios públicos.

Actualizado