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.
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.
Authorization: Bearer tq_test_EXEMPLE
Content-Type: application/jsonIdempotencia
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.
{
"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.
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).
{
"error": {
"code": "invalid_request",
"message": "El campo \"to\" debe ser un número en formato E.164.",
"request_id": "req_EXEMPLE_002"
}
}| HTTP | code | Significado | Acción recomendada |
|---|---|---|---|
| 400 | invalid_request | Solicitud mal formada: campo ausente o inválido, falta Idempotency-Key en un POST. | Corrija la solicitud. |
| 401 | unauthorized | Clave ausente, inválida o revocada. | Revise la clave y la cabecera Authorization. |
| 403 | forbidden | La clave no tiene permiso para acceder a este recurso o proyecto. | Use una clave con los permisos adecuados. |
| 404 | not_found | El recurso no existe o está fuera de su alcance. | Revise el identificador. |
| 409 | idempotency_conflict | Misma Idempotency-Key usada con un cuerpo distinto. | Genere una clave nueva. |
| 429 | rate_limited | Ritmo 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.
{
"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.
{
"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).
{
"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).
{
"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.
{
"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).
{
"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.
{
"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
| Objeto | Estados | Observación |
|---|---|---|
| Llamada | ringing, connected, completed, failed | failed no indica la causa. No la suponga. |
| SMS | queued, sent, delivered, undelivered, unknown | delivered no significa leído. unknown puede quedar como estado final. |
| Pedido de número | pending_validation | El 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.
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.