Talkyria · API v1.0.0

Talkyria API

API pública de autoservicio de Talkyria — la plataforma de confirmación de pedidos contraentrega (COD) con voz IA para LATAM.

Autenticación. Todas las peticiones usan un Bearer token: Authorization: Bearer tk_live_.... Las claves se generan en el dashboard (Integraciones → API). Usa claves de sandbox tk_test_... para desarrollar sin telefonía ni cobros reales.

Scopes. Cada clave tiene scopes granulares (o acceso total). Un endpoint responde 403 insufficient_scope (con required_scope) si la clave no tiene el scope necesario. Scopes: orders:read, orders:write, calls:trigger, calls:read, calls:read:content, agents:read, agents:write, voices:read, leads:write, leads:read, offers:read, offers:write, analytics:read, webhooks:read, webhooks:write, billing:read, phones:read, phones:write, verified_caller_ids:read, verified_caller_ids:write.

Sandbox. Las claves tk_test_ cortocircuitan los endpoints que disparan llamadas o mutan estado (POST /calls/trigger, POST /orders/:id/calls, POST /calls/bulk, POST /test-call, PATCH /orders/:id/status, POST /sales/agents/:id/leads, POST /webhooks/external-confirmation) devolviendo { test: true, status: "test_simulated", ... } — sin telefonía, sin cobro. La gestión de agentes y smart-offers NO está en sandbox (es configuración, sin llamadas ni billing).

Rate limit. Por ventana de 60s y por clave: 1200 lecturas (GET), 600 escrituras (POST/PATCH/PUT/DELETE), 120 en sandbox (tk_test_). Además un tope por tienda de 2000/min (varias claves de una misma tienda no multiplican el límite). Excederlo devuelve 429 rate_limit con cabeceras X-RateLimit-* y Retry-After.

Contenido sensible. El transcript y la grabación de una llamada solo aparecen si la clave tiene el scope calls:read:content. La grabación es un enlace estable /rec/<token>, nunca la URL cruda de S3.

Saldo. Disparar llamadas requiere saldo. Sin saldo ni minutos disponibles (y sin auto-recarga activa), POST /calls/trigger responde 402.

Idempotencia. Los POST que crean un recurso sin una clave natural — POST /agents (crear agente) y POST /phones (comprar número, cobra saldo) — aceptan una cabecera Idempotency-Key: <valor-único> (8–255 chars). Si reintentas con la misma clave, la API reproduce EXACTAMENTE la respuesta original (mismo status y cuerpo) en vez de crear un segundo recurso o cobrar dos veces; una petición concurrente con la misma clave responde 409 idempotency_conflict. Genera una clave nueva (p.ej. un UUID) por operación lógica; se recuerdan 24h. POST /calls/trigger ya es idempotente por su externalId: reintentar con el mismo externalId devuelve el pedido existente (409 duplicate_order) y nunca dispara una segunda llamada.

Reintentos. Las respuestas 429 (rate limit) y 409 no_voice_engine (el agente aún se está creando en el motor) incluyen una cabecera Retry-After con los segundos exactos a esperar antes de reintentar.

Frontera. La API es un reino disjunto: nunca expone funciones de super-admin ni infraestructura. Todo está limitado al workspace de la clave. Solo existe /api/v1 — para siempre, aditivo.

https://api.talkyria.com/api/v1https://app.talkyria.com/api/v1openapi.json ↗

Orders

Pedidos: consulta, historial de llamadas y estado logístico.

get/ordersorders:read

Listar pedidos

Busca pedidos del shop. Requiere scope orders:read.

Parámetros

phonequerystringTeléfono del cliente (E.164).
externalIdquerystring
shopifyOrderIdquerystring
limitqueryinteger
offsetqueryinteger

Respuestas

200Lista paginada.
401Unauthorized
403Forbidden
get/orders/{id}orders:read

Obtener un pedido

Detalle del pedido + sus llamadas. El transcript y la grabación de cada llamada requieren además el scope calls:read:content. Requiere scope orders:read.

Parámetros

idreqpathstring

Respuestas

200Pedido con sus llamadas.
401Unauthorized
403Forbidden
404Error
get/orders/{id}/callscalls:read

Llamadas de un pedido

Requiere scope calls:read (+ calls:read:content para transcript/grabación).

Parámetros

idreqpathstring

Respuestas

200Llamadas.
401Unauthorized
403Forbidden
404Error
post/orders/{id}/callscalls:trigger

Re-llamar un pedido existente

Encola una llamada manual para un pedido EXISTENTE (equivalente al botón "Llamar" del dashboard). Corre los mismos billing guards + rate-limit (1 llamada por pedido cada 5 min) y marca la llamada como manual (bypassa dedup). Para ingerir un pedido NUEVO + llamarlo usa POST /calls/trigger. Requiere scope calls:trigger. Saldo: sin saldo ni minutos (y sin auto-recarga), responde 402. Sandbox: claves tk_test_ simulan sin telefonía ni cobro.

Parámetros

idreqpathstring

Respuestas

200Encolada, programada (fuera de horario), o simulada (sandbox).
400Error
401Unauthorized
402Sin saldo: recarga el wallet o activa la auto-recarga.
403Forbidden
404Error
405Error
429Ya hay una llamada reciente para este pedido (espera unos minutos).
patch/orders/{id}/statusorders:write

Actualizar estado logístico

Actualiza el estado logístico del pedido. Requiere scope orders:write. Sandbox: claves tk_test_ devuelven una respuesta simulada sin mutar.

Parámetros

idreqpathstring

Body (requerido)

logisticStatus"processing" | "shipped" | "in_transit" | "delivered" | "returned" | "failed_delivery"
trackingNumberstring
carrierstring

Respuestas

200Actualizado (o simulado en sandbox).
400Error
401Unauthorized
403Forbidden
404Error
405Error
post/webhooks/external-confirmationorders:write

Confirmar/cancelar un pedido externamente

Marca un pedido como confirmed o cancelled desde un sistema externo (ej. una confirmación por WhatsApp), suspende los reintentos y etiqueta el pedido en Shopify si aplica. First-write-wins: un pedido ya confirmado no se sobrescribe. Requiere scope orders:write. Sandbox: las claves tk_test_ simulan sin mutar el pedido real.

Host: https://app.talkyria.com/api/v1

Body (requerido)

statusreq"confirmed" | "cancelled"
orderIdstringid / externalId / chateaproOrderId del pedido
orderNumberstring
shopifyOrderIdstring
sourcestring
confirmedBystring
notesstring

Respuestas

200Actualizado (o `already_confirmed` si ya estaba confirmado).
400Error
401Unauthorized
403Forbidden
404Error
429RateLimited

Calls

Disparar llamadas y leer su metadata/outcome.

get/callscalls:read

Listar llamadas

Lista global de llamadas del shop, paginada + filtrable. Requiere scope calls:read (+ calls:read:content para transcript/grabación, offers:read para el resultado de oferta). Nunca expone costos internos ni el resumen crudo.

Parámetros

outcomequerystringFiltro por outcome (confirmed, no_answer, voicemail, ...).
statusquerystring
callTypequerystringconfirmation / novelty / office / cart_recovery / sales / ...
phonequerystringTeléfono del cliente (E.164).
fromquerystring (date-time)
toquerystring (date-time)
limitqueryinteger
offsetqueryinteger

Respuestas

200Lista de llamadas.
401Unauthorized
403Forbidden
429RateLimited
get/calls/{id}calls:read

Obtener una llamada

Metadata/outcome de una llamada. Requiere scope calls:read (+ calls:read:content para transcript/grabación). Nunca expone costos internos ni el resumen crudo.

Parámetros

idreqpathstring

Respuestas

200Llamada.
401Unauthorized
403Forbidden
404Error
post/calls/triggercalls:trigger

Disparar una llamada

Crea un pedido y encola una llamada. Requiere scope calls:trigger. Acepta el shape plano (canónico) y el anidado (order:{}) legacy — ambos equivalen. Saldo: sin saldo ni minutos (y sin auto-recarga), responde 402. Sandbox: claves tk_test_ simulan sin telefonía ni cobro.

Body (requerido)

Objeto TriggerRequest (ver Esquemas).

Respuestas

200Pausada, duplicada, o simulada (sandbox).
201Encolada.
400Error
401Unauthorized
402Sin saldo: recarga el wallet o activa la auto-recarga.
403Forbidden
get/calls/bulkcalls:read

Listar batches de llamadas

Los 20 batches más recientes del shop, con su progreso. Requiere scope calls:read.

Respuestas

200Batches.
401Unauthorized
403Forbidden
post/calls/bulkcalls:trigger

Iniciar un batch de llamadas

Crea + inicia un batch de llamadas. Requiere scope calls:trigger. Provee orderIds (array de ids del shop) o status (todos los pedidos con ese status, opcional limit). El bulkCallWorker procesa SECUENCIALMENTE y re-valida cada pedido antes de llamar (se salta los ya confirmados). Tope: 500 pedidos/batch. Sandbox: claves tk_test_ simulan sin telefonía ni cobro.

Body (requerido)

orderIdsstring[]Pedidos explícitos (shop-scoped).
statusstringAlternativa: todos los pedidos con este status.
limitintegerLímite para el filtro por status.
customMotifstring

Respuestas

200Simulado (sandbox).
201Batch iniciado.
400Error
401Unauthorized
403Forbidden
404Error
405Error
502No se pudo encolar el batch.
get/calls/bulk/{id}calls:read

Estado de un batch

Status + progreso (procesados/exitosos/fallidos) de un batch. Requiere scope calls:read. Shop-scoped.

Parámetros

idreqpathstring

Respuestas

200Batch.
401Unauthorized
403Forbidden
404Error
post/calls/bulk/{id}calls:trigger

Controlar un batch (pausar/reanudar/cancelar)

Pausa, reanuda o cancela un batch en curso. Requiere scope calls:trigger. Transiciones válidas: pause (in_progress), resume (paused), cancel (pending/in_progress/paused). Shop-scoped.

Parámetros

idreqpathstring

Body (requerido)

actionreq"pause" | "resume" | "cancel"

Respuestas

200Aplicado.
400Error
401Unauthorized
403Forbidden
404Error
405Error
502No se pudo reanudar el batch.
post/test-callcalls:trigger

Llamada de prueba a un agente

Realiza una llamada de PRUEBA con un agente para validar tu configuración. Requiere scope calls:trigger. Body: agentTable (ShopifyAgent|ChateaProAgent|DropiAgent|SalesAgent), agentId (del shop), phoneNumber (E.164). La llamada se factura normal (wallet/minutos) y usa la misma resolución de número que las llamadas reales (verificado > dedicado). Sandbox: claves tk_test_ simulan sin telefonía ni cobro.

Body (requerido)

agentTablereq"ShopifyAgent" | "ChateaProAgent" | "DropiAgent" | "SalesAgent"
agentIdreqstring
phoneNumberreqstringE.164 con código de país (+573001234567).

Respuestas

200Llamada de prueba iniciada (o simulada en sandbox).
400Error
401Unauthorized
402Sin saldo: recarga el wallet.
403Forbidden
405Error
502No se pudo iniciar la llamada de prueba.

Agents

Crear, editar, listar y borrar agentes de voz.

get/agentsagents:read

Listar agentes

Lista los agentes del shop (todas las integraciones). Requiere scope agents:read. No expone el prompt.

Respuestas

200Agentes.
401Unauthorized
403Forbidden
post/agentsagents:write

Crear un agente

Crea un agente de voz de cualquier integración (shopify | chateapro | dropi | sales, según integration, default shopify). Requiere scope agents:write. Reusa el core probado del dashboard (validación de voz/modelo, dedup por tipo/callType, creación del counterpart en el motor de voz + workflow canónico, con borrado del huérfano si el motor falla). Un agente sin número nace inactivo (Regla 87).

Host: https://app.talkyria.com/api/v1

Body (requerido)

Objeto CreateAgentRequest (ver Esquemas).

Respuestas

201Creado.
400Error
401Unauthorized
403Forbidden
409Dedup (ya existe un agente de ese tipo/status) o cuota alcanzada.
502Fallo al crear el counterpart en el motor de voz.
get/agents/{id}agents:read

Obtener un agente

Configuración completa del agente. Requiere scope agents:read. El prompt personalizado solo aparece si el agente lo usa.

Parámetros

idreqpathstring

Respuestas

200Agente.
401Unauthorized
403Forbidden
404Error
patch/agents/{id}agents:write

Editar un agente

Edita campos del agente (voz, idioma, reintentos, nombre, estado, número, horarios, cupón, y los específicos de cada integración). La integración se resuelve automáticamente por el id (across shopify/chateapro/dropi/sales). Requiere scope agents:write. Solo se aceptan campos editables — cualquier otro se ignora (allowlist per-integración). Activar un agente (isActive:true) requiere que tenga número (Regla 87). Reusa el core probado del dashboard.

Host: https://app.talkyria.com/api/v1

Parámetros

idreqpathstring

Body (requerido)

Objeto UpdateAgentRequest (ver Esquemas).

Respuestas

200Actualizado (puede incluir `warning` si un side-effect no bloqueante falló).
400Error
401Unauthorized
403Forbidden
404Error
409Conflicto (dedup de tipo/status).
502El número se guardó pero no se pudo sincronizar al motor de voz.
delete/agents/{id}agents:write

Borrar un agente

Borra permanentemente el agente (hard-delete, Regla 323) de cualquier integración — la integración se resuelve por el id. Dropi/Sales cascadean sus dependientes (smart-offers / leads). Requiere scope agents:write.

Host: https://app.talkyria.com/api/v1

Parámetros

idreqpathstring

Respuestas

200Eliminado.
401Unauthorized
403Forbidden
404Error
get/agents/{id}/advancedagents:read

Leer la configuración avanzada del agente

Los knobs avanzados de comportamiento de llamada (timbrado/silencio/duración/backchannel), buzón de voz, diccionario de palabras clave (boost STT), campos de análisis post-llamada y handbook de personalidad. De cualquier integración (resuelto por el id). Requiere scope agents:read.

Host: https://app.talkyria.com/api/v1

Parámetros

idreqpathstring

Respuestas

200Configuración avanzada.
401Unauthorized
403Forbidden
404Error
patch/agents/{id}/advancedagents:write

Actualizar la configuración avanzada (parcial)

Actualiza SOLO los campos enviados; los omitidos se preservan. Persiste en el snapshot del agente y sincroniza el motor de voz best-effort (si el motor falla, el cambio queda guardado y se reintenta en la próxima llamada → respuesta con warning). voicemail.action siempre es hangup. Requiere scope agents:write.

Host: https://app.talkyria.com/api/v1

Parámetros

idreqpathstring

Body (requerido)

Objeto AdvancedConfig (ver Esquemas).

Respuestas

200Configuración actualizada.
400Error
401Unauthorized
403Forbidden
404Error
500Error

Workflow

Flujo conversacional completo del agente (Nivel B).

get/agents/{id}/workflowagents:read

Leer el flujo del agente

Devuelve el workflow_definition (máquina de estados conversacional) del agente, de cualquier integración (resuelto por el id). Requiere scope agents:read.

Host: https://app.talkyria.com/api/v1

Parámetros

idreqpathstring

Respuestas

200Flujo.
401Unauthorized
403Forbidden
404Error
409El agente aún no tiene counterpart en el motor de voz.
put/agents/{id}/workflowagents:write

Reemplazar el flujo del agente (Nivel B)

Reemplaza el workflow_definition completo. Requiere scope agents:write. El motor valida invariantes (exactamente 1 nodo de inicio, 1 nodo global, aristas con etiqueta/condición, variables de contexto canónicas). Un flujo que viola una invariante irrecuperable devuelve 422 con la lista exacta de errores — las llamadas nunca quedan mudas por un flujo malformado.

Host: https://app.talkyria.com/api/v1

Parámetros

idreqpathstring

Body (requerido)

workflow_definitionreqWorkflowDefinition
template_context_variablesobject

Respuestas

200Flujo actualizado.
400Error
401Unauthorized
403Forbidden
409El agente aún no tiene counterpart en el motor de voz.
422El flujo viola una invariante irrecuperable.
502Fallo del motor de voz.

Voices

Catálogo de voces.

get/voicesvoices:read

Catálogo de voces

Voces disponibles para los agentes. Requiere scope voices:read.

Parámetros

languagequerystringFiltro por prefijo de idioma (ej. `es`).

Respuestas

200Voces.
401Unauthorized
403Forbidden
502Catálogo de voces temporalmente no disponible.

Leads

Leads de ventas (speed-to-lead).

get/sales/agents/{id}/leadsleads:read

Listar leads de ventas

Lista los leads de un agente de ventas (estado, outcome, venta). Requiere scope leads:read. Filtro status, paginado. NUNCA el fee interno ni el metadata crudo.

Parámetros

idreqpathstringID del agente de ventas.
statusquerystringFiltro por estado (queued, sold, not_interested, ...).
limitqueryinteger
offsetqueryinteger

Respuestas

200Lista de leads.
401Unauthorized
403Forbidden
404Error
429RateLimited
post/sales/agents/{id}/leadsleads:write

Crear un lead de ventas

Encola un lead para que el agente de ventas lo llame (speed-to-lead). Requiere scope leads:write. Sandbox: claves tk_test_ simulan sin crear lead ni llamar. Rate-limit adicional de 60/min por shop.

Parámetros

idreqpathstringID del agente de ventas.

Body (requerido)

namereqstring
phonereqstringE.164, mín 8 dígitos.
emailstring (email)
sourcestring
sourceLeadIdstring
metadataobject

Respuestas

200Duplicado (dedup 24h) o simulado (sandbox).
201Encolado.
400Error
401Unauthorized
403Forbidden
404Error
405Error
429RateLimited

Offers

Resultados de upsell / smart-offers (revenue conversation intelligence).

get/orders/{id}/offersoffers:read

Resultados de upsell del pedido

Si el upsell/smart-offer se mostró, si el cliente aceptó, qué producto/cantidad/variante, cuánto revenue generó y si el line-item se agregó a Shopify. Requiere scope offers:read.

Parámetros

idreqpathstring

Respuestas

200Resultados de upsell.
401Unauthorized
403Forbidden
404Error
get/offersoffers:read

Listar smart-offers

Config + stats de las smart-offers del shop (upsell/quantity/bundle). Requiere scope offers:read. ?integration=shopify|dropi filtra por integración; ?agentId= filtra las de Dropi por agente. Los agregados (timesShown/timesAccepted/revenueGenerated) son SOLO LECTURA (los escribe el worker).

Parámetros

integrationquery"shopify" | "dropi"
agentIdquerystringFiltro Dropi por agente.

Respuestas

200Ofertas por integración.
400Error
401Unauthorized
403Forbidden
post/offersoffers:write

Crear una smart-offer

Crea una smart-offer. Requiere scope offers:write. El body DEBE incluir integration ("shopify" | "dropi"). Shopify: oferta shop-global (el precio con descuento se recomputa server-side). Dropi: requiere agentId y habilita enableSmartOffers del agente (LOCK provider/warehouse). Los agregados NUNCA se pueden escribir.

Body (requerido)

integrationreq"shopify" | "dropi"
namestring
offerType"upsell" | "quantity" | "bundle"
agentIdstringRequerido para Dropi.

Respuestas

201Creada.
400Error
401Unauthorized
403Forbidden
405Error
get/offers/{id}offers:read

Obtener una smart-offer

Detalle de una smart-offer (resuelve Shopify y Dropi). Requiere scope offers:read. Shop-scoped.

Parámetros

idreqpathstring

Respuestas

200Oferta.
401Unauthorized
403Forbidden
404Error
patch/offers/{id}offers:write

Editar una smart-offer

Edita una smart-offer (incluye toggle vía isActive). Requiere scope offers:write. Dropi: agentId es inmutable. Shop-scoped.

Parámetros

idreqpathstring

Body (requerido)

object

Respuestas

200Actualizada.
400Error
401Unauthorized
403Forbidden
404Error
405Error
delete/offers/{id}offers:write

Borrar una smart-offer

Borra una smart-offer (hard delete). Requiere scope offers:write. Dropi: si era la última oferta activa del agente, apaga enableSmartOffers. Shop-scoped.

Parámetros

idreqpathstring

Respuestas

200Borrada.
401Unauthorized
403Forbidden
404Error
405Error

Analytics

Métricas agregadas (tasas, outcomes, funnel, por-agente).

get/analyticsanalytics:read

Analytics agregado

Métricas agregadas del shop (tasas de confirmación, breakdown de outcomes, serie temporal, heatmap por hora, por-producto/ciudad/agente, funnel, cart recovery, ofertas). Requiere scope analytics:read. NUNCA expone el costo interno de Talkyria — solo lo que se le cobra al merchant (Regla 387).

Host: https://app.talkyria.com/api/v1

Parámetros

presetquery"this_month" | "last_7d" | "last_30d" | "all"
fromquerystring (date)
toquerystring (date)
sourcequerystringFiltro de canal (shopify/dropi/chateapro/sales).
agentquerystringFiltro por id de agente.

Respuestas

200Analytics.
401Unauthorized
403Forbidden

Webhooks

Webhooks salientes: recibe el resultado final de cada llamada en tiempo real (sin polling).

get/webhookswebhooks:read

Listar webhooks salientes

Lista los webhooks salientes del shop. Requiere scope webhooks:read. NUNCA devuelve el secret.

Respuestas

200Webhooks.
401Unauthorized
403Forbidden
429RateLimited
post/webhookswebhooks:write

Registrar un webhook saliente

Registra una URL a la que Talkyria hace PUSH del resultado final de cada llamada (call.outcome_final), firmado con X-Talkyria-Signature: sha256=hmac(payloadRaw, secret), con reintentos (1/5/30 min) e idempotencia. Requiere scope webhooks:write. La URL se valida contra SSRF (bloquea IPs internas/metadata, resuelve DNS). El secret se genera server-side y se muestra UNA sola vez en la respuesta. Máximo 10 webhooks por shop.

Body (requerido)

urlreqstring (uri)URL pública HTTPS del receptor.
eventsstringSuscripción a eventos, separados por coma (Regla 421). Por defecto `call.outcome_final` (recibe TODOS los resultados). Granulares: `call.confirmed`, `call.cancelled`, `call.no_answer`, `call.voicemail`, `call.novelty`, `call.needs_attention`, `call.failed`. Ej. `call.confirmed,call.no_answer` recibe solo esos. El payload lleva `event` (siempre el umbrella, compat) + `eventType` (el granular); el header `X-Talkyria-Event-Type` también trae el granular.
merchantExternalIdstring

Respuestas

201Creado. Incluye el `secret` (guárdalo — no se vuelve a mostrar).
400URL no permitida (SSRF / formato).
401Unauthorized
403Forbidden
405Error
409Máximo de webhooks por shop alcanzado.
429RateLimited
get/webhooks/{id}webhooks:read

Detalle de un webhook

Detalle de un webhook del shop (sin secret). Requiere scope webhooks:read.

Parámetros

idreqpathstring

Respuestas

200Webhook.
401Unauthorized
403Forbidden
404Error
429RateLimited
patch/webhooks/{id}webhooks:write

Editar un webhook

Edita url (revalidada anti-SSRF), events, isActive o merchantExternalId. Con regenerateSecret: true rota el secreto (se muestra una vez). Requiere scope webhooks:write.

Parámetros

idreqpathstring

Body (opcional)

urlstring (uri)
eventsstring
isActiveboolean
merchantExternalIdstring
regenerateSecretboolean

Respuestas

200Actualizado. Incluye `secret` solo si se regeneró.
400Error
401Unauthorized
403Forbidden
404Error
429RateLimited
delete/webhooks/{id}webhooks:write

Borrar un webhook

Borra un webhook del shop. Requiere scope webhooks:write.

Parámetros

idreqpathstring

Respuestas

200Borrado.
401Unauthorized
403Forbidden
404Error
429RateLimited
get/webhooks/{id}/deliverieswebhooks:read

Historial de entregas de un webhook

Historial de entregas de un webhook saliente (status code, éxito, intento, respuesta del destino) para depurar. Requiere scope webhooks:read. Paginado. El secreto NUNCA aparece; responseBody se trunca a 2000 chars.

Parámetros

idreqpathstring
limitqueryinteger
offsetqueryinteger

Respuestas

200Entregas.
401Unauthorized
403Forbidden
404Error
429RateLimited

Billing

Cuenta: saldo, tarifa, minutos gratis y contexto de la clave (solo lectura).

get/walletbilling:read

Saldo y tarifa (solo lectura)

Saldo del wallet + tarifa por minuto + minutos gratis restantes + config de auto-recarga. Requiere scope billing:read. SOLO LECTURA — la recarga/transferencia NUNCA se expone por API (Stripe/dashboard/2FA). Nunca expone el costo interno de Talkyria.

Respuestas

200Wallet.
401Unauthorized
403Forbidden
429RateLimited
get/mebilling:read

Contexto de la clave (who am I)

Shop, workspace, país/moneda, plan, scopes y modo prueba de la clave. Requiere scope billing:read. Nunca secretos ni costo interno.

Respuestas

200Contexto.
401Unauthorized
403Forbidden
429RateLimited

Phones

get/phonesphones:read

Listar teléfonos dedicados

Números dedicados activos del workspace. Requiere scope phones:read. Nunca expone el carrier (Regla 119).

Host: https://app.talkyria.com/api/v1

Respuestas

200Teléfonos.
401Unauthorized
403Forbidden
429RateLimited
post/phonesphones:write

Comprar un teléfono dedicado (FACTURA el wallet)

Compra el número phoneNumber (de GET /phones/available) y lo importa al motor de voz. Cobra $2.00 USD/mes al wallet del workspace. Requiere scope phones:write. Divergencias vs dashboard (seguridad programática): verifica saldo ANTES (402 si insuficiente), cuota máx 25/workspace (409), y una clave tk_test_ NO compra (respuesta simulada). El número se compra NEUTRAL — asígnalo con PATCH /agents/:id { phoneNumberId }.

Host: https://app.talkyria.com/api/v1

Body (requerido)

phoneNumberreqstring

Respuestas

201Comprado.
400Error
401Unauthorized
402Saldo insuficiente para la compra.
403Forbidden
409Cuota de teléfonos excedida o conflicto de credenciales SIP.
429RateLimited
502Fallo al comprar/provisionar el número.
get/phones/availablephones:read

Buscar números disponibles

Números US comprables. areaCode opcional (3 dígitos). Requiere scope phones:read. Read-only (sin costo).

Host: https://app.talkyria.com/api/v1

Parámetros

areaCodequerystringArea code US (3 dígitos).

Respuestas

200Disponibles.
401Unauthorized
403Forbidden
429RateLimited
502Error
patch/phones/{id}phones:write

Renombrar (alias) un teléfono

Cambia el alias nickname. Requiere scope phones:write.

Host: https://app.talkyria.com/api/v1

Parámetros

idreqpathstring

Body (requerido)

nicknamereqstring

Respuestas

200Renombrado.
400Error
401Unauthorized
403Forbidden
404Error
429RateLimited
delete/phones/{id}phones:write

Liberar un teléfono dedicado

Lo desasigna de todos los agentes + lo libera en el motor/carrier. NO reembolsa. Requiere scope phones:write. Una clave tk_test_ no libera infra real.

Host: https://app.talkyria.com/api/v1

Parámetros

idreqpathstring

Respuestas

200Liberado.
401Unauthorized
403Forbidden
404Error
429RateLimited

Verified Caller IDs

get/verified-caller-idsverified_caller_ids:read

Listar Verified Caller IDs

Los números propios del merchant verificados (+ estado). Requiere scope verified_caller_ids:read.

Host: https://app.talkyria.com/api/v1

Respuestas

200Verified Caller IDs.
401Unauthorized
403Forbidden
429RateLimited
post/verified-caller-idsverified_caller_ids:write

Solicitar verificación de un número propio

Inicia la verificación del número propio phoneNumber (E.164). Telnyx lo llama (method:call) o textea (method:sms) con un código. Luego envíalo con POST .../:id/verify. Requiere scope verified_caller_ids:write. Sin costo. Una clave tk_test_ no dispara la verificación real.

Host: https://app.talkyria.com/api/v1

Body (requerido)

phoneNumberreqstring
method"call" | "sms"

Respuestas

201Verificación iniciada.
400Error
401Unauthorized
403Forbidden
429RateLimited
502Error
delete/verified-caller-ids/{id}verified_caller_ids:write

Eliminar un Verified Caller ID

Lo borra en el motor/carrier + limpia las asignaciones de agente. Requiere scope verified_caller_ids:write.

Host: https://app.talkyria.com/api/v1

Parámetros

idreqpathstring

Respuestas

200Eliminado.
401Unauthorized
403Forbidden
404Error
429RateLimited
post/verified-caller-ids/{id}/verifyverified_caller_ids:write

Enviar el código de verificación

Envía el código (4-10 dígitos) que Telnyx dictó/texteó. Síncrono: OK ⇒ status:verified. Requiere scope verified_caller_ids:write. Luego asigna con PATCH /agents/:id { verifiedCallerIdId }.

Host: https://app.talkyria.com/api/v1

Parámetros

idreqpathstring

Body (requerido)

codereqstring

Respuestas

200Verificado.
400Error
401Unauthorized
403Forbidden
404Error
429RateLimited
502Error

Esquemas

Las formas de datos referenciadas arriba.

Error
errorreqstringMensaje de error legible por humanos.
code"bad_request" | "unauthorized" | "payment_required" | "forbidden" | "not_found" | "conflict" | "unprocessable_entity" | "rate_limited" | "internal_error" | "error"Código de error estable legible por máquina (Regla 422). Haz switch por este campo, no por el mensaje.
messagestringMensaje adicional legible por humanos (presente en algunos endpoints).
Order
idstring
shopifyOrderIdstring
externalIdstring
externalSourcestring
orderNumberstring
statusstring
customerNamestring
customerPhonestring
customerCitystring
totalPricenumber
itemsSummarystring
logisticStatusstring
trackingNumberstring
carrierstring
callAttemptsinteger
cityFinalstring
provinceFinalstring
confirmationChannelstringQuién confirmó: call | whatsapp | cross_integration.
attentionReasonstring
confirmedAtstring (date-time)
createdAtstring (date-time)
OrderDetail

any

Call
idstring
callTypestring
statusstring
outcomestring
durationSecondsinteger
summarystring
notesForHumanstring
cancelReasonstring
resolutionInstructionstringInstrucción operativa generada por IA (novedades/logística).
analysisobjectAnálisis post-llamada tipado (allowlisted, no-PII).
sentimentstring
wrongNumberboolean
addressChangedboolean
productConfirmedboolean
priceConfirmedboolean
offerobjectResultado de upsell — solo con scope `offers:read`.
shownboolean
acceptedboolean
productTitlestring
disconnectionReasonstring
fromNumberstring
createdAtstring (date-time)
transcriptstringSolo con scope `calls:read:content`.
recordingUrlstringEnlace estable `/rec/<token>`. Solo con scope `calls:read:content`.
OfferResult
idstring
callIdstring
typestringupsell | quantity | bundle
namestring
shownboolean
acceptedboolean
productTitlestring
discountedPricenumber
quantityAcceptedinteger
chosenVariantTitlestring
revenueUsdnumberRevenue del upsell (GMV del merchant).
lineItemAddedToShopifyboolean
shopifyErrorstring
createdAtstring (date-time)
BulkBatch
idstring
statusstringpending | in_progress | paused | cancelled | completed
totalinteger
processedinteger
succeededinteger
failedinteger
customMotifstring
createdAtstring (date-time)
updatedAtstring (date-time)
Agent
idstring
integrationstring
typestring
namestring
triggerStatusesstring[]
isActiveboolean
voiceobject
idstring
namestring
languagestring
voiceReadyboolean
hasCallerNumberboolean
createdAtstring (date-time)
AgentDetail

any

Voice
voiceIdstring
namestring
languagestring
accentstring
genderstring
tierstring
isMultilingualboolean
previewUrlstring
Phone

Número dedicado (merchant-safe — nunca expone el carrier interno, Regla 119).

idstring
phoneNumberstring
nicknamestring
countrystring
monthlyPriceUsdnumber
isActiveboolean
purchasedAtstring (date-time)
nextBillingAtstring (date-time)
VerifiedCallerId

Número propio del merchant verificado (Camino 1). Nunca expone el detalle de fallo de Telnyx.

idstring
phoneNumberstring
countrystring
status"pending" | "verified" | "failed"
verificationMethod"call" | "sms"
verifiedAtstring (date-time)
lastTestCallAtstring (date-time)
createdAtstring (date-time)
TriggerRequest

Dispara una llamada. Shape CANÓNICO = PLANO (los campos de orden en la raíz). Por compatibilidad, el endpoint TAMBIÉN acepta el shape ANIDADO legacy (`order:{ externalId, products, totalPrice, currency }` + `address:{}`) — ambos producen el mismo resultado. Sólo `externalId` + `customer.phone` son obligatorios (agente-first): para un agente contraentrega manda producto/precio/dirección; para un agente API genérico manda tu propio contexto en `customVariables`.

externalIdreqstringID del pedido en tu sistema (clave de idempotencia).
callType"confirmation" | "novelty" | "office"
sourcestringDe dónde viene la llamada (ej. tu CRM). Opcional; default `api`. También aceptado como `metadata.source`.
agentIdstringAgente exacto a marcar (custom trigger). Obligatorio para agentes API-native; opcional para integraciones (aplica ruteo por status cuando se omite).
merchantExternalIdstringTu ID de merchant (opcional).
customerreqobject
namestring
phonereqstringE.164, ej. +573001234567.
emailstring
nsstringContact NS de ChateaPro (opcional).
productsobject[]Opcional. Productos del pedido.
namestring
quantityinteger
pricestring
totalPricestringOpcional. Valor total (string numérico).
currencystring
shippingAddressobject
address1string
address2string
citystring
provincestring
countryCodestring
metadataobjectObjeto libre. `metadata.source` es una alternativa a `source`.
customVariablesobjectVariables custom del cliente que el agente puede hablar. La clave DEBE empezar por `cv_` (charset `[a-z0-9_]`, máx 40); máx 25 claves, valor string ≤200 chars (se recorta). Se sanitizan server-side. Para que se hablen, referéncialas en el workflow del agente (Nivel B) como `{{cv_xxx}}`.
CreateAgentRequest

Crear un agente. `integration` selecciona el tipo (default `shopify`). Campos requeridos adicionales por integración: **shopify** → `type`; **chateapro/dropi** → `triggerStatuses` (+ `triggerCallType` obligatorio en chateapro); **sales** → `productName`, `productPrice`, `currency`, `paymentType`. Campos no aplicables a la integración se ignoran.

integration"shopify" | "chateapro" | "dropi" | "sales"
namereqstring
type"confirmation" | "cart_recovery" | "prepaid" | "dispatch_cod" | "dispatch_prepaid" | "custom"Solo shopify.
triggerCallType"confirmation" | "novelty" | "office" | "delivery" | "dispatched" | "delivered" | "devolucion"chateapro (obligatorio) / dropi.
descriptionstring
triggerStatusesstring[]shopify / chateapro / dropi.
voiceIdstring
languagestring
maxRetriesinteger
retryDelayMinutesinteger
maxCallDurationinteger
callDelaySecondsinteger
phoneNumberIdstring
enableVoicemailDetectionboolean
customPromptstring
useCustomPromptboolean
workingHoursobject
respectboolean
startstring
endstring
daysinteger[]
timezonestring
offHoursActionstring
callMode"AUTO" | "MANUAL"Solo dropi.
duplicateMode"WINDOW" | "OFF"Solo dropi.
discountEnabledboolean
discountCodestring
discountType"percent" | "fixed"
discountValuenumber
productNamestringSolo sales (requerido).
productPricestringSolo sales (requerido).
currencystringSolo sales (requerido).
paymentTypestringSolo sales (requerido).
productDetailsstring
quantityOfferEnabledboolean
upsellEnabledboolean
objectionsstring
UpdateAgentRequest

Todos los campos son opcionales. Solo se aplican los presentes (allowlist per-integración). Además de los listados: **chateapro/dropi** aceptan `triggerCallType`; **dropi** acepta `callMode`/`duplicateMode`/`exclusionGroup`; **sales** acepta sus campos de producto/oferta (`productName`, `productPrice`, `currency`, `paymentType`, `objections`, `upsellEnabled`, `metaPixelId`, `metaCapiToken`, …).

integrationstringIgnorado — la integración se resuelve por el id.
triggerCallType"confirmation" | "novelty" | "office" | "delivery" | "dispatched" | "delivered" | "devolucion"chateapro/dropi.
namestring
descriptionstring
triggerStatusesstring[]
voiceIdstring
languagestring
customPromptstring
useCustomPromptboolean
maxRetriesinteger
retryDelayMinutesinteger
retryScheduleJsonstring
maxCallDurationinteger
callModestring
callDelaySecondsinteger
phoneNumberIdstring
verifiedCallerIdIdstring
isActiveboolean
enableVoicemailDetectionboolean
duplicateModestring
duplicateCallWindowHoursinteger
discountEnabledboolean
discountCodestring
discountTypestring
discountValuenumber
workingHoursobject
respectboolean
startstring
endstring
daysinteger[]
timezonestring
offHoursActionstring
retryHoursobject
respectboolean
startstring
endstring
daysanyCSV o array de días.
WorkflowDefinition

Grafo del flujo conversacional. El motor valida invariantes al guardar.

nodesreqobject[]
idstring
typestring
positionobject
dataobject
edgesobject[]
idstring
sourcestring
targetstring
dataobject
global_node_idstring
AdvancedConfig

Configuración avanzada del agente. En PATCH todos los campos son opcionales (los omitidos se preservan).

ring_duration_msintegerDuración del timbrado (ms).
max_call_duration_msintegerDuración máxima de la llamada (ms).
end_call_after_silence_msintegerColgar tras silencio total (ms).
enable_backchannelbooleanAcks naturales (ajá/mhm) mientras el cliente habla.
voicemailobject
enabledbooleanDetección de buzón de voz.
action"hangup"Siempre `hangup` (el motor cuelga al detectar buzón).
speech_cutoff_secondsinteger
system_promptstring
dictionaryobject[]Palabras clave (boost STT). PATCH reemplaza la lista completa.
phrasereqstring
boostinteger
phoneticstring
analysis_fieldsobject[]Campos de análisis post-llamada. PATCH reemplaza la lista completa.
typereq"boolean" | "string" | "enum" | "number"
namereqstring
descriptionstring
choicesstring[]Solo type=enum.
handbookobjectToggles de personalidad.
default_personalityboolean
natural_filler_wordsboolean
high_empathyboolean
echo_verificationboolean
nato_phonetic_alphabetboolean
speech_normalizationboolean
smart_matchingboolean
ai_disclosureboolean
scope_boundariesboolean
WebhookEndpoint

Un webhook saliente registrado. El `secret` NUNCA se incluye aquí.

idstring
urlstring (uri)
eventsstringEventos suscritos, separados por coma (Regla 421). `call.outcome_final` = todos; o granulares `call.confirmed`/`call.cancelled`/`call.no_answer`/`call.voicemail`/`call.novelty`/`call.needs_attention`/`call.failed`.
isActiveboolean
merchantExternalIdstring
createdAtstring (date-time)
WebhookEndpointWithSecret

Webhook con el `secret` incluido — devuelto SOLO al crearlo o al regenerarlo (una vez).

secretstringSecreto HMAC (`whsec_…`). Verifica cada entrega con `X-Talkyria-Signature`. No se vuelve a mostrar.
messagestring