HTTP API v1
Acceso programático a números de teléfono, llamadas, SMS, buzones de voz y funciones de IA. JSON sobre HTTPS. Idempotente cuando importa. No se requiere SDK, pero enviamos 5.
Introducción
La API de NoKYCNumber está organizada en torno a REST. Usamos URLs orientadas a recursos predecibles, aceptamos y devolvemos cuerpos codificados en JSON, y usamos códigos de respuesta HTTP estándar, autenticación y verbos.
URL base
https://api.nokycnumber.com/v1/Todas las peticiones deben realizarse mediante HTTPS. Las llamadas por HTTP simple fallarán con 301 Moved Permanently. Las peticiones sin autenticación fallarán con 401 Unauthenticated.
Convención JSON
- Todas las peticiones con cuerpo usan
Content-Type: application/json. Los cuerpos codificados como formulario se rechazan con415. - Las marcas de tiempo se devuelven como cadenas ISO-8601 UTC (
2026-04-26T14:23:00Z) y se aceptan en el mismo formato. - Los números de teléfono se devuelven en formato E.164 con un
+inicial (+33647189022) y formateados endisplaycuando sea relevante. - Los IDs de objeto llevan el prefijo de su recurso:
num_,call_,sms_,vm_,whk_,evt_.
Autenticación
Autentícate con una clave bearer emitida desde tu panel en Ajustes → Claves API. Existen dos tipos de clave:
sk_live_…— secreto del lado del servidor. Lectura/escritura completa. Nunca expongas en código del cliente.pk_live_…— clave publicable. Actualmente reservada; aún no utilizada por ningún endpoint.
Formato de cabecera
Authorization: Bearer sk_live_5f3a8b2c4d1e9f6a7b8c2d1e9f6a7b8c
Content-Type: application/json
NoKYC-Version: 2026-04-01Usa la cabecera NoKYC-Version para fijar una versión específica de la API (ver Versiones). Si se omite, se usa el predeterminado fijado de tu cuenta.
Alcances
Las claves se emiten con uno de tres alcances:
| Alcance | Métodos permitidos | Caso de uso |
|---|---|---|
read | GET | Informes, paneles de monitorización. |
read_write | GET · POST · PATCH | La mayoría de las integraciones del lado del servidor. |
admin | Todo incluyendo DELETE | Automatización de aprovisionamiento, gestión de cuentas. |
Las claves se pueden rotar en cualquier momento. Las claves antiguas siguen siendo válidas durante 5 minutos tras la rotación para permitir despliegues sin tiempo de inactividad.
Errores
La API usa códigos de estado HTTP convencionales. 2xx significa éxito, 4xx significa un problema con tu solicitud, 5xx significa que cometimos un error y nos gustaría saberlo.
Sobre de error
{
"error": {
"type": "invalid_request_error",
"code": "parameter_missing",
"message": "Required parameter `country` is missing.",
"param": "country",
"request_id": "req_8a4c2f1e9b3d4a7c"
}
}Códigos de estado
| Código | Significado |
|---|---|
200 | OK · solicitud exitosa |
201 | Creado · recurso creado |
204 | Sin contenido · recurso eliminado, sin cuerpo devuelto |
400 | Solicitud incorrecta · JSON malformado o parámetro requerido faltante |
401 | Sin autenticar · clave API inválida, faltante o revocada |
402 | Pago requerido · saldo de cuenta insuficiente para la acción |
403 | Prohibido · la clave no tiene el alcance necesario para esta operación |
404 | No encontrado · el recurso no existe o pertenece a otra cuenta |
409 | Conflicto · clave de idempotencia reutilizada con parámetros diferentes |
422 | No procesable · error semántico (p.ej. país no soportado) |
429 | Demasiadas solicitudes · ver Límites de velocidad |
500 – 503 | Problema de servidor / servicio · seguro reintentar con retroceso exponencial |
Tipos de error
invalid_request_error— entrada malformada, campos faltantes, formato inválido.authentication_error— problema con la clave.authorization_error— problema de alcance.rate_limit_error— reduce la velocidad.api_error— error nuestro. Reintentable.resource_error— el estado del recurso impide la operación (p.ej., intentar realizar una llamada desde un número pausado).upstream_error— el operador o socio superó el tiempo de espera.
Cada respuesta de error incluye un request_id. Regístralo siempre — es la única forma de que nuestro soporte pueda correlacionar tu llamada con nuestra traza interna.
Paginación
Los endpoints de lista usan paginación de cursor solo hacia adelante. Devuelven hasta limit objetos (por defecto 25, máx. 100) y un booleano has_more. Para obtener la página siguiente, pasa el id del último objeto como starting_after.
curl https://api.nokycnumber.com/v1/numbers?limit=10 \
-H "Authorization: Bearer sk_live_…"{
"object": "list",
"url": "/v1/numbers",
"data": [
{ "id": "num_8a4c2f1e9b3d", "object": "number", "number": "+33647189022", … },
{ "id": "num_2k7m9p3w8x4t", "object": "number", "number": "+12025550143", … }
],
"has_more": true,
"next_cursor": "num_2k7m9p3w8x4t"
}Las listas están ordenadas con los objetos más recientes primero. La paginación hacia atrás mediante ending_before no está soportada — navega mediante el cursor.
Idempotencia
Las peticiones POST que modifican estado aceptan una cabecera Idempotency-Key. Deduplicamos por la clave durante 24 horas, devolviendo la respuesta en caché para reintentos. Usa un UUID por operación lógica.
POST /v1/sms HTTP/1.1
Authorization: Bearer sk_live_…
Idempotency-Key: 9b3d4a7c-8a4c-2f1e-9b3d-4a7c8a4c2f1e
Content-Type: application/json
{ "from": "num_8a4c2f1e9b3d", "to": "+33612345678", "body": "Hello" }Reutilizar la misma clave con contenido de cuerpo diferente devuelve 409 Conflict con idempotency_key_mismatch.
Las claves de idempotencia no son obligatorias, pero se recomiendan encarecidamente para cualquier operación que tenga coste (llamadas, SMS, compras de números). Sin una, un reintento de red puede cobrarte dos veces.
Límites de velocidad
Por defecto, cada clave API está limitada a 100 solicitudes por minuto. Los clientes de alto volumen pueden solicitar un aumento al soporte. Los límites se aplican por clave, no por IP.
Cabeceras de respuesta
X-Rate-Limit-Limit: 100
X-Rate-Limit-Remaining: 73
X-Rate-Limit-Reset: 1745672460
Retry-After: 8Cuando superas el límite, recibes 429 Too Many Requests con una cabecera Retry-After en segundos. Se recomienda un retroceso lineal de hasta 4 reintentos; si persiste, solicita un límite más alto.
Margen de ráfaga
El limitador es un cubo de tokens — se toleran ráfagas cortas por encima de 100 rpm siempre que el promedio móvil de 60 segundos se mantenga por debajo del límite.
Versiones
Las versiones de la API tienen fecha (2026-04-01). Los cambios incompatibles se publican como una nueva versión con fecha; las adiciones compatibles se incluyen en la actual. Fija una versión con la cabecera NoKYC-Version.
Compatibilidad
- Damos soporte a cada versión durante al menos 24 meses después del siguiente lanzamiento.
- Los avisos de obsolescencia se envían por email a los propietarios de cuentas con 90 días de antelación.
- Una cabecera de respuesta
NoKYC-Deprecationavisa cuando estás en una versión obsoleta.
Versión actual: 2026-04-01.
Números
Un número representa una línea telefónica virtual que controlas. Los números están vinculados a un país y un tipo (mobile o landline) y tienen un período de facturación.
/v1/numbers
Lista todos los números de tu cuenta. Devuelve una lista paginada de objetos number.
| Field | Tipo | Description |
|---|---|---|
limit opcional | integer | 1–100, por defecto 25. |
starting_after opcional | string | Cursor para paginación. |
country opcional | string | Filtra por código de país ISO-2 (p.ej. fr). |
type opcional | string | Filtra por mobile o landline. |
status opcional | string | Filtra por active, paused o released. |
curl https://api.nokycnumber.com/v1/numbers?country=fr&type=mobile \
-H "Authorization: Bearer sk_live_…"{
"object": "list",
"data": [
{
"id": "num_8a4c2f1e9b3d",
"object": "number",
"number": "+33647189022",
"display": "+33 6 47 18 90 22",
"country": "fr",
"type": "mobile",
"tier": "standard",
"status": "active",
"billing_period": "yearly",
"renews_at": "2027-04-26T11:23:00Z",
"ai_enabled": true,
"created_at": "2026-04-26T11:23:00Z"
}
],
"has_more": false,
"next_cursor": null
}/v1/numbers/available
Busca en el inventario los números disponibles en un país y tipo determinados. Usa el id devuelto al llamar a POST /v1/numbers.
| Field | Tipo | Description |
|---|---|---|
country requerido | string | Código de país ISO-2. |
type requerido | string | mobile o landline. |
tier opcional | string | standard (por defecto) o premium. |
pattern opcional | string | Filtro de subcadena opcional en dígitos locales, p.ej. "77". |
limit opcional | integer | 1–50, por defecto 10. |
curl "https://api.nokycnumber.com/v1/numbers/available?country=fr&type=mobile&tier=premium&limit=5" \
-H "Authorization: Bearer sk_live_…"{
"object": "list",
"data": [
{ "id": "navail_2k7m9p3w8x4t", "number": "+33611112222", "display": "+33 6 11 11 22 22", "tier": "premium", "pattern": "double-repeat", "price_usd_per_month": 11.98 },
{ "id": "navail_4n2v8j1q6h7y", "number": "+33612345678", "display": "+33 6 12 34 56 78", "tier": "premium", "pattern": "sequential", "price_usd_per_month": 11.98 }
],
"expires_at": "2026-04-26T11:33:00Z"
}Los números disponibles se reservan durante 10 minutos. Tras su vencimiento, el mismo id puede asignarse a otro usuario.
/v1/numbers
Activa un número nuevo a partir de un id de reserva. Carga el período configurado en el saldo de tu cuenta.
| Field | Tipo | Description |
|---|---|---|
available_id requerido | string | Un id navail_… de /v1/numbers/available. |
billing_period requerido | string | monthly, quarterly, o yearly. |
addons opcional | array | Complementos de IA a activar, p.ej. ["ai-pickup","ai-trans"]. |
webhook_url opcional | string | Endpoint que recibirá los eventos del número. |
curl https://api.nokycnumber.com/v1/numbers \
-H "Authorization: Bearer sk_live_…" \
-H "Idempotency-Key: 9b3d4a7c-8a4c-2f1e-9b3d-4a7c8a4c2f1e" \
-d '{
"available_id": "navail_2k7m9p3w8x4t",
"billing_period": "yearly",
"addons": ["ai-pickup"]
}'{
"id": "num_8a4c2f1e9b3d",
"object": "number",
"number": "+33611112222",
"display": "+33 6 11 11 22 22",
"country": "fr",
"type": "mobile",
"tier": "premium",
"status": "active",
"billing_period": "yearly",
"renews_at": "2027-04-26T11:23:00Z",
"ai_enabled": true,
"created_at": "2026-04-26T11:23:00Z"
}/v1/numbers/{id}
Recupera un número individual por id.
curl https://api.nokycnumber.com/v1/numbers/num_8a4c2f1e9b3d \
-H "Authorization: Bearer sk_live_…"/v1/numbers/{id}
Actualiza campos modificables de un número. Usa POST /v1/numbers/{id}/renew para extender el período.
| Field | Tipo | Description |
|---|---|---|
auto_renew opcional | boolean | Activa/desactiva la renovación automática al final del período. |
webhook_url opcional | string | Reemplaza el destino del webhook del número. |
addons opcional | array | Reemplaza el conjunto activo de complementos de IA. |
on_off opcional | object | Establece horas silenciosas / ventanas desactivadas. Consulta Configuración de IA. |
/v1/numbers/{id}
Libera un número. El número vuelve al inventario al final del período y puede ser reasignado a otro cliente. Devuelve 204 No Content.
curl -X DELETE https://api.nokycnumber.com/v1/numbers/num_8a4c2f1e9b3d \
-H "Authorization: Bearer sk_live_…"Los números liberados no pueden recuperarse. Recomendamos pausar primero mediante PATCH con { "status": "paused" } si podrías querer recuperarlo.
Llamadas
Una llamada es una sesión de voz iniciada desde uno de tus números. Las llamadas salientes se realizan mediante POST /v1/calls; las entrantes se replican a tu webhook y también son recuperables a través de la API.
/v1/callsRealiza una llamada saliente desde uno de tus números.
| Field | Tipo | Description |
|---|---|---|
from requerido | string | Un id num_ que posees. |
to requerido | string | Destino E.164, p.ej. +33612345678. |
recording_enabled opcional | boolean | Por defecto false. Las grabaciones se almacenan 30 días. |
callerid_mask opcional | string | "hide", "rotate", o cualquier número E.164 que poseas. |
metadata opcional | object | JSON arbitrario devuelto en los webhooks para la llamada. |
curl https://api.nokycnumber.com/v1/calls \
-H "Authorization: Bearer sk_live_…" \
-d '{
"from": "num_8a4c2f1e9b3d",
"to": "+33612345678",
"callerid_mask": "rotate"
}'{
"id": "call_2k7m9p3w8x4t",
"object": "call",
"from": "num_8a4c2f1e9b3d",
"from_e164": "+33647189022",
"to": "+33612345678",
"status": "ringing",
"direction": "outbound",
"started_at": "2026-04-26T11:24:01Z",
"answered_at": null,
"ended_at": null,
"duration_sec": 0,
"recording_url": null,
"cost_usd": null
}/v1/callsLista llamadas. Filtra por number, direction, status, o created_after / created_before.
/v1/calls/{id}Recupera una llamada individual.
/v1/calls/{id}/hangupFinaliza forzosamente una llamada en curso. Idempotente.
Mensajes SMS
Envía y recupera SMS. Los mensajes largos se segmentan automáticamente según las reglas GSM-03.38 / UCS-2; la respuesta muestra el número real de segmentos para la facturación.
/v1/smsEnvía un SMS desde uno de tus números.
| Field | Tipo | Description |
|---|---|---|
from requerido | string | Un id num_ que posees. |
to requerido | string | Destino E.164. |
body requerido | string | Cuerpo del mensaje. Máx. 1.600 caracteres (10 segmentos). |
send_at opcional | string | Marca de tiempo futura en ISO-8601 para programar la entrega. |
media_urls opcional | array | Hasta 5 URLs de imagen/vídeo. Solo MMS — funciona en países compatibles. |
curl https://api.nokycnumber.com/v1/sms \
-H "Authorization: Bearer sk_live_…" \
-H "Idempotency-Key: 9b3d4a7c-8a4c-2f1e-9b3d-4a7c8a4c2f1e" \
-d '{
"from": "num_8a4c2f1e9b3d",
"to": "+33612345678",
"body": "Bonjour. Your code is 482917."
}'{
"id": "sms_4n2v8j1q6h7y",
"object": "sms",
"from_e164": "+33647189022",
"to": "+33612345678",
"body": "Bonjour. Your code is 482917.",
"direction": "outbound",
"segments": 1,
"status": "queued",
"created_at": "2026-04-26T11:24:50Z",
"delivered_at": null,
"cost_usd": 0.012
}/v1/smsLista mensajes. Filtra por number, direction, status.
/v1/sms/{id}Recupera un mensaje individual incluyendo el estado de entrega a nivel de segmento.
Buzones de voz
Los buzones de voz se almacenan, transcriben y traducen automáticamente. Las URLs de audio están prefirmadas y caducan 1 hora después de su emisión.
/v1/voicemailsLista buzones de voz. Paginación idéntica a otros endpoints de lista.
/v1/voicemails/{id}Recupera un buzón de voz individual con transcripción y URL de audio.
{
"id": "vm_5p3w8x4t9k2m",
"object": "voicemail",
"number_id": "num_8a4c2f1e9b3d",
"from_e164": "+33612345678",
"received_at": "2026-04-26T11:25:42Z",
"duration_sec": 27,
"audio_url": "https://files.nokycnumber.com/vm/5p3w8x4t9k2m.mp3?expires=1745676342&sig=…",
"transcript": {
"text": "Bonjour, c'est Marc. Rappelez-moi quand vous pouvez.",
"language": "fr",
"translation_en": "Hello, this is Marc. Call me back when you can.",
"summary": "Marc asks for a callback.",
"sentiment": "neutral"
}
}Tanto translation_en como summary requieren el complemento ai-summary.
/v1/voicemails/{id}Elimina permanentemente un buzón de voz y su archivo de audio. Devuelve 204 No Content.
Configuración de IA
Cada número puede ejecutar un agente de IA que contesta llamadas cuando no puedes, filtra llamantes desconocidos, resume buzones de voz o traduce conversaciones en tiempo real. Configúralo por número mediante el subrecurso de IA.
/v1/numbers/{id}/aiRecupera la configuración de IA actual de un número.
{
"object": "ai_config",
"number_id": "num_8a4c2f1e9b3d",
"addons": ["ai-pickup", "ai-summary"],
"auto_pickup": {
"enabled": true,
"after_rings": 4,
"script": "I'm unavailable right now. Leave your name, the reason for the call, and a callback number.",
"language": "auto",
"voice": "neutral_fr"
},
"screening": { "enabled": false },
"translator": { "enabled": false, "target_language": "en" },
"voicemail_summary": { "enabled": true, "include_sentiment": true }
}/v1/numbers/{id}/aiActualiza una o más funciones de IA. Cada bloque es opcional; solo se actualizan los campos presentes.
Voces
Voces disponibles: neutral_en, neutral_fr, neutral_es, neutral_de, neutral_jp, warm_en, warm_fr. Voces clonadas personalizadas para empresas bajo solicitud.
Cuenta
Lee datos a nivel de cuenta: saldo, estadísticas de uso, webhooks configurados.
/v1/accountRecupera tu cuenta.
{
"object": "account",
"email_hash": "9b3d4a7c8a4c2f1e",
"balance_usd": 47.32,
"default_country": "fr",
"active_numbers": 3,
"monthly_call_minutes": 412,
"monthly_sms_segments": 1820,
"created_at": "2026-04-12T09:15:00Z"
}/v1/account/usageDesglose detallado de uso para el período actual. Pasa period=last_30d o period=last_90d.
Webhooks
Suscríbete a eventos de tu cuenta o números específicos. Enviamos un evento JSON por POST a tu endpoint y reintentamos hasta 5 veces con retroceso exponencial en 24 horas.
Sobre de evento
{
"id": "evt_3d4a7c8a4c2f",
"object": "event",
"type": "sms.received",
"created": "2026-04-26T11:25:42Z",
"livemode": true,
"data": { "object": { "id": "sms_…", … } },
"request_id": "req_8a4c2f1e9b3d4a7c"
}Verificación de firma
Cada solicitud lleva una cabecera X-NoKYC-Signature en la forma t=<ts>,v1=<hex>. La firma es HMAC-SHA256 de <ts>.<raw_body> usando el secreto de firma del endpoint. Rechaza cualquier solicitud con más de 5 minutos de antigüedad.
# Pseudocode
ts, v1 = parse(header)
if abs(now - ts) > 300: reject
expected = hmac_sha256(secret, f"{ts}.{body}")
if not constant_time_eq(expected, v1): rejectEndpoints
/v1/webhook_endpointsRegistra un nuevo endpoint de webhook. Devuelve el secreto de firma una sola vez; guárdalo.
| Field | Tipo | Description |
|---|---|---|
url requerido | string | URL HTTPS a la que enviaremos eventos por POST. |
enabled_events requerido | array | Lista de suscripción, p.ej. ["sms.received","call.completed"]. Usa ["*"] para todos. |
description opcional | string | Nota libre para tu propio registro. |
/v1/webhook_endpointsLista tus endpoints.
/v1/webhook_endpoints/{id}Elimina un endpoint. Devuelve 204.
Tipos de evento
| Evento | Se activa cuando |
|---|---|
number.activated | Se ha aprovisionado un número nuevo y está listo. |
number.renewed | Renovación del período exitosa. |
number.paused | El número entró en estado pausado por ventana activa/inactiva. |
number.released | Número liberado permanentemente al inventario. |
call.initiated | Llamada saliente realizada. |
call.answered | El interlocutor remoto contestó. |
call.completed | Llamada finalizada (cualquier motivo). |
call.recorded | Grabación finalizada y disponible. |
sms.received | SMS entrante recibido en tu número. |
sms.sent | SMS saliente aceptado por el operador. |
sms.delivered | Acuse de entrega del operador confirmado. |
sms.failed | Operador rechazó — verifica failure_code. |
voicemail.created | Nuevo buzón de voz grabado y transcrito. |
ai.pickup | La respuesta automática de IA contestó una llamada. |
account.balance_low | El saldo cayó por debajo del umbral configurado. |
Esquemas de objetos
number
{
"id": "string · num_…",
"object": "string · constant \"number\"",
"number": "string · E.164",
"display": "string · pretty-printed",
"country": "string · ISO-2",
"type": "enum · mobile | landline",
"tier": "enum · standard | premium",
"tier_pattern": "string | null · double-repeat | sequential | mirror | round | …",
"status": "enum · active | paused | released",
"billing_period": "enum · monthly | quarterly | yearly",
"renews_at": "string · ISO-8601 UTC",
"auto_renew": "boolean",
"addons": "array · ai-pickup | ai-screen | ai-summary | ai-trans",
"ai_enabled": "boolean",
"metadata": "object | null",
"created_at": "string · ISO-8601 UTC"
}call
{
"id": "string · call_…",
"object": "string · constant \"call\"",
"from": "string · num_…",
"from_e164": "string · E.164",
"to": "string · E.164",
"direction": "enum · inbound | outbound",
"status": "enum · queued | ringing | in_progress | completed | failed | no_answer | busy",
"started_at": "string · ISO-8601 UTC",
"answered_at": "string | null",
"ended_at": "string | null",
"duration_sec": "integer",
"recording_url": "string | null · pre-signed, expires in 1h",
"cost_usd": "number | null"
}sms
{
"id": "string · sms_…",
"object": "string · constant \"sms\"",
"from": "string · num_…",
"from_e164": "string · E.164",
"to": "string · E.164",
"body": "string",
"media_urls": "array · up to 5",
"direction": "enum · inbound | outbound",
"segments": "integer · 1–10",
"status": "enum · queued | sent | delivered | failed | undelivered",
"failure_code": "string | null",
"created_at": "string · ISO-8601 UTC",
"delivered_at": "string | null",
"cost_usd": "number | null"
}SDKs oficiales
La HTTP API es la fuente de verdad, pero estos SDKs te proporcionan bindings tipados, reintentos, idempotencia y verificación de webhooks de fábrica.
-
node
npm install @nokycnumber/sdk -
python
pip install nokycnumber -
go
go get github.com/nokycnumber/sdk-go -
php
composer require nokycnumber/sdk -
ruby
gem install nokycnumber