Referencia de la API de demostración

Esta página describe la API tal como está diseñada hoy: autenticación, idempotencia, paginación, errores, puntos de acceso y webhooks. Es una versión de demostración. Todos los ejemplos son ficticios.

Actualizado el

Estado de esta referencia

Se trata de una propuesta de diseño que puede cambiar sin previo aviso. Hoy no hay ninguna API de producción abierta.

Mientras no haya un proveedor configurado, las llamadas, los pedidos de números y los SMS son simulaciones. Las respuestas incluyen entonces el campo simulated: true.

Los ejemplos usan el dominio ficticio api.example.test, la clave ficticia tq_test_EXEMPLE y números de un rango ficticio. Ninguno da acceso real.

Dirección base y autenticación

Todas las solicitudes pasan por la base https://api.example.test/v1, mediante HTTPS. Autentíquese con una clave de API en la cabecera Authorization, con el esquema Bearer.

Una clave está limitada a un proyecto y a un entorno. No debe aparecer nunca en código que se ejecute en el navegador ni en una URL.

Ejemplo ficticio: cabecera de autenticación. La clave es inventada.
Authorization: Bearer tq_test_EXEMPLE
Content-Type: application/json

Idempotencia

Toda solicitud POST exige una cabecera Idempotency-Key con un identificador único, por ejemplo un UUID. Sin ella, la API responde 400 invalid_request.

Si reenvía la misma clave con el mismo cuerpo, la API repite la respuesta original y no crea nada más: un doble clic o un reintento de red no tiene efecto. Si reenvía la misma clave con un cuerpo distinto, la API responde 409 idempotency_conflict.

Genere una clave nueva para cada operación nueva. Si una respuesta no llegó nunca, reintente con la misma clave y no con una nueva.

Paginación por cursor

Las listas aceptan limit y cursor. La respuesta contiene la matriz data y next_cursor. Para leer la página siguiente, pase el valor de next_cursor en cursor. Cuando next_cursor es nulo, la lista ha terminado.

Un cursor es opaco: no lo decodifique ni lo construya usted mismo.

Ejemplo ficticio del final de una lista.
{
  "data": [],
  "next_cursor": null
}

Cuotas y límites de ritmo

La API limita el ritmo de las solicitudes. Superado el límite, responde 429 rate_limited con una cabecera Retry-After que indica, en segundos, cuánto esperar antes de reintentar.

Los límites aplicables a su proyecto dependen de su contrato. En esta página no se publica ninguna cifra.

Ejemplo ficticio de respuesta 429.
HTTP/1.1 429 Too Many Requests
Retry-After: 2
Content-Type: application/json

{ "error": { "code": "rate_limited", "message": "Demasiadas solicitudes. Reintente tras el plazo indicado.", "request_id": "req_EXEMPLE_001" } }

Formato de los errores

Todo error devuelve un objeto error con tres campos: code (estable, para usar en su lógica), message (pensado para una persona, puede cambiar) y request_id (para indicar al soporte).

Ejemplo ficticio de respuesta de error.
{
  "error": {
    "code": "invalid_request",
    "message": "El campo \"to\" debe ser un número en formato E.164.",
    "request_id": "req_EXEMPLE_002"
  }
}
HTTPcodeSignificadoAcción recomendada
400invalid_requestSolicitud mal formada: campo ausente o inválido, falta Idempotency-Key en un POST.Corrija la solicitud.
401unauthorizedClave ausente, inválida o revocada.Revise la clave y la cabecera Authorization.
403forbiddenLa clave no tiene permiso para acceder a este recurso o proyecto.Use una clave con los permisos adecuados.
404not_foundEl recurso no existe o está fuera de su alcance.Revise el identificador.
409idempotency_conflictMisma Idempotency-Key usada con un cuerpo distinto.Genere una clave nueva.
429rate_limitedRitmo de solicitudes demasiado alto.Espere el tiempo de Retry-After.

GET /numbers

Lista los números de su cuenta.

  • limit: número de elementos por página (opcional).
  • cursor: cursor de la página siguiente (opcional).
  • Cada número incluye id, e164, country, type, capabilities (voice, sms), project_id y status.
Ejemplo ficticio de respuesta. Datos de demostración.
{
  "data": [
    {
      "id": "num_EXEMPLE_001",
      "e164": "+33199001234",
      "country": "FR",
      "type": "local",
      "capabilities": ["voice", "sms"],
      "project_id": "prj_EXEMPLE_A",
      "status": "active"
    }
  ],
  "next_cursor": "cur_EXEMPLE_002"
}

GET /numbers/search

Busca números en el inventario. La disponibilidad real depende del país, del proveedor elegido y del contrato.

  • country: país en código ISO de dos letras, por ejemplo FR.
  • type: tipo de número, por ejemplo local.
  • Cada resultado incluye e164, country, type, capabilities y documents_required, la lista de documentos que deben aportarse antes de la activación.
Ejemplo ficticio de respuesta. El valor de documents_required es ilustrativo.
{
  "data": [
    {
      "e164": "+33199001234",
      "country": "FR",
      "type": "local",
      "capabilities": ["voice", "sms"],
      "documents_required": ["proof_of_address"]
    }
  ]
}

POST /number-orders

Realiza un pedido de número. La cabecera Idempotency-Key es obligatoria. El pedido queda a la espera de la validación de los documentos y las condiciones.

  • e164: número que se pide, obtenido de una búsqueda (obligatorio).
  • project_id: proyecto al que se asocia (obligatorio).
Ejemplo ficticio de respuesta. Simulación: no se reserva ningún número real.
{
  "id": "ord_EXEMPLE_001",
  "status": "pending_validation",
  "simulated": true
}

POST /calls

Inicia una llamada saliente entre dos números. La cabecera Idempotency-Key es obligatoria.

  • from: número que llama, en E.164 (obligatorio).
  • to: número llamado, en E.164 (obligatorio).
  • project_id: proyecto afectado (obligatorio).
  • flow_id: escenario de llamada que se aplica (opcional).
Ejemplo ficticio de respuesta. Simulación: no se emitió ninguna comunicación real.
{
  "id": "call_EXEMPLE_001",
  "status": "ringing",
  "simulated": true
}

GET /calls

Lista el registro de llamadas, con paginación por cursor. Las duraciones están en segundos. La duración de conversación y la duración facturable son dos campos distintos: pueden diferir según el contrato.

  • limit y cursor: paginación (opcionales).
  • Cada llamada incluye id, direction, status, duration_seconds, billable_seconds y project_id.
Ejemplo ficticio de respuesta. Datos de demostración.
{
  "data": [
    {
      "id": "call_EXEMPLE_001",
      "direction": "outbound",
      "status": "completed",
      "duration_seconds": 42,
      "billable_seconds": 42,
      "project_id": "prj_EXEMPLE_A"
    }
  ],
  "next_cursor": null
}

POST /messages

Envía o programa un SMS. La cabecera Idempotency-Key es obligatoria. Un texto largo se divide en segmentos, y cada uno cuenta para el consumo.

  • from: remitente (obligatorio).
  • to: destinatario, en E.164 (obligatorio).
  • text: contenido del mensaje (obligatorio).
  • nature: transactional o marketing (obligatorio).
  • scheduled_at: fecha y hora de un envío programado (opcional).
  • timezone: zona horaria de scheduled_at (opcional, se indica junto con scheduled_at).
  • La respuesta indica segments y encoding (GSM-7 o UCS-2).
Ejemplo ficticio de respuesta. Simulación: no se envió ningún SMS real.
{
  "id": "msg_EXEMPLE_001",
  "status": "queued",
  "segments": 1,
  "encoding": "GSM-7",
  "simulated": true
}

GET /usage

Devuelve las cantidades consumidas durante un período. La respuesta contiene cantidades y unidades, nunca importes.

  • from y to: límites del período, en formato AAAA-MM-DD.
  • group_by: day, number, project, country o service.
  • provisional vale true cuando aún pueden llegar eventos con retraso.
  • Una llamada puede generar varias líneas de consumo según el contrato.
Ejemplo ficticio de respuesta. Valores inventados.
{
  "data": [
    { "key": "2026-10-01", "service": "voice", "direction": "outbound", "unit": "second", "quantity": 5400 },
    { "key": "2026-10-01", "service": "sms", "direction": "outbound", "unit": "segment", "quantity": 120 }
  ],
  "provisional": false
}

Estados

ObjetoEstadosObservación
Llamadaringing, connected, completed, failedfailed no indica la causa. No la suponga.
SMSqueued, sent, delivered, undelivered, unknowndelivered no significa leído. unknown puede quedar como estado final.
Pedido de númeropending_validationEl número solo se puede usar tras la activación (evento number.activated).

Webhooks

Puede recibir eventos en una dirección HTTPS de su elección. Cada entrega incluye una cabecera Telqio-Signature con la forma t=<marca de tiempo unix>,v1=<firma hexadecimal>.

La firma es un HMAC-SHA256 del texto «t, punto, cuerpo sin procesar» con el secreto del punto de conexión. Rechace toda entrega cuya marca de tiempo se aleje más de 300 segundos y deduplique por el identificador de evento id.

Eventos: call.ringing, call.connected, call.completed, call.failed, message.sent, message.delivered, message.undelivered y number.activated. Los reintentos de entrega siguen una política acotada, visible en la consola. No se garantiza el orden de llegada.

La guía «Verifique un webhook firmado» ofrece el código completo en Node.js.

Ejemplo ficticio de una entrega. La forma exacta del sobre puede cambiar.
POST /webhook HTTP/1.1
Telqio-Signature: t=1794096000,v1=<firma_hexadecimal>
Content-Type: application/json

{
  "id": "evt_EXEMPLE_001",
  "type": "call.completed",
  "created": 1794096000,
  "data": { "call_id": "call_EXEMPLE_001", "status": "completed" }
}

Lo que esta referencia no es

  • No es un compromiso de servicio: no se promete ninguna disponibilidad, plazo ni capacidad.
  • No es una API abierta: no existe ninguna clave real y no se emite ninguna comunicación.
  • Las capacidades reales dependerán del país, del proveedor elegido y del contrato. Para su alcance, solicite un presupuesto.

Preguntas frecuentes

¿Puedo usar esta API en producción?

No. Es una versión de demostración. No hay ninguna API de producción abierta y el contrato de la interfaz aún puede cambiar.

¿Por qué las respuestas contienen simulated: true?

Porque no hay ningún proveedor configurado. Las llamadas, los SMS y los pedidos de números son simulados, y no se emite ninguna comunicación real.