Orders
Pedidos: consulta, historial de llamadas y estado logístico.
Calls
Disparar llamadas y leer su metadata/outcome.
Agents
Crear, editar, listar y borrar agentes de voz.
Workflow
Flujo conversacional completo del agente (Nivel B).
Voices
Catálogo de voces.
Leads
Leads de ventas (speed-to-lead).
Offers
Resultados de upsell / smart-offers (revenue conversation intelligence).
Analytics
Métricas agregadas (tasas, outcomes, funnel, por-agente).
Webhooks
Webhooks salientes: recibe el resultado final de cada llamada en tiempo real (sin polling).
Billing
Cuenta: saldo, tarifa, minutos gratis y contexto de la clave (solo lectura).
Phones
Números dedicados: comprar, listar, asignar a un agente y liberar.
Verified Caller IDs
Números propios verificados: solicitar el código, confirmarlo y usarlos como identificador de llamada.
Llamadas
Esquemas
Las formas de datos que referencian las operaciones.
Error
{
"code": "not_found",
"message": "string",
"error": "Order not found",
"correctUrl": "https://…",
"correctHost": "api.talkyria.com",
"docs": "string"
}codereq"bad_request" | "unauthorized" | "payment_required" | "forbidden" | "not_found" | "conflict" | "unprocessable_entity" | "rate_limited" | "rate_limit" | "internal_error" | "error" | "missing_auth" | "invalid_api_key" | "key_expired" | "insufficient_scope" | "validation_error" | "invalid_json" | "wrong_host" | "method_not_allowed"Código estable legible por máquina. **Es el único campo por el que debes ramificar.** Los códigos de la lista son los transversales; muchos endpoints devuelven además uno más específico de su dominio (`order_not_found`, `billing_inactive`, `shop_ambiguous`, `idempotency_conflict`, `no_voice_engine`, `wrong_engine`…). Trata un código desconocido como un fallo de su familia de estado HTTP.
messagereqstringTexto humano del error. Siempre presente.
errorreqstringLEGADO — no ramifiques por este campo. En `api.talkyria.com` lleva el mensaje humano; en `app.talkyria.com` lleva el código. Se conserva para no romper a quien ya lo lee, pero su significado depende del host. Usa `code` (máquina) y `message` (humano).
correctUrlstringSólo con `code: "wrong_host"`. URL exacta a la que reenviar la petición.
correctHoststringSólo con `code: "wrong_host"`. Host que sí sirve la operación.
docsstringEnlace a la documentación de la operación.
OrderLogisticsLogística del pedido (aditivo, 2026-09-15). Reúne lo que antes venía plano más la última novedad conocida.
{
"carrier": "Servientrega",
"trackingNumber": "ABC123456789",
"logisticStatus": "string",
"noveltyText": "string",
"lastIncidenceAt": "2026-09-09T14:32:00.000Z"
}carrierstringtrackingNumberstringlogisticStatusstringTexto libre del canal — ver la nota en `Order.logisticStatus`.
noveltyTextstringTexto de la última novedad reportada por la transportadora, si la hubo.
lastIncidenceAtstring (date-time)
OrderInsightsHuella digital del comprador y datos de la dirección según Dropi (aditivo, 2026-09-15). `null` cuando el pedido no tiene datos de Dropi. Nunca incluye datos financieros del comercio.
{
"riskLevel": "alto",
"riskReasons": [
"string"
],
"addressValidated": false,
"merchantTags": [
"string"
],
"origin": "string",
"buyerHistory": {
"total": 0,
"delivered": 0,
"returned": 0,
"deliveryRate": 0
},
"coverageCod": false,
"carrierName": "Servientrega",
"cityName": "Bogotá"
}riskLevel"alto" | "medio" | "bajo" | "null"Riesgo del comprador según su historial de entregas y devoluciones en Dropi.
riskReasonsstring[]addressValidatedbooleantrue si la transportadora validó la dirección.
merchantTagsstring[]Etiquetas que el comercio puso al pedido en Dropi.
originstringDe dónde nació el pedido en Dropi (shopify, chateapro, manual…).
buyerHistoryobjectHuella digital del comprador en Dropi: pedidos hechos, recibidos y devueltos, y el porcentaje recibido sobre los terminados.
- └
totalinteger - └
deliveredinteger - └
returnedinteger - └
deliveryRateinteger0-100: % de pedidos terminados que el comprador recibió. null sin pedidos terminados.
coverageCodbooleantrue si la ciudad tiene cobertura de pago contraentrega con esa transportadora.
carrierNamestringcityNamestring
Order
{
"id": "ord_a1b2c3",
"shopifyOrderId": "5891234567890",
"externalId": "MI-PEDIDO-001",
"externalSource": "string",
"orderNumber": "1042",
"status": "confirmed",
"customerName": "María González",
"customerPhone": "+573001234567",
"customerCity": "Bogotá",
"totalPrice": 0,
"itemsSummary": "1x Faja Reductora Talla M",
"logisticStatus": "PENDIENTE CONFIRMACION",
"trackingNumber": "ABC123456789",
"carrier": "Servientrega",
"callAttempts": 0,
"cityFinal": "Bogotá",
"provinceFinal": "Cundinamarca",
"confirmationChannel": "string",
"attentionReason": "string",
"confirmedAt": "2026-09-09T14:32:00.000Z",
"createdAt": "2026-09-09T14:32:00.000Z",
"logistics": {
"carrier": "Servientrega",
"trackingNumber": "ABC123456789",
"logisticStatus": "string",
"noveltyText": "string",
"lastIncidenceAt": "2026-09-09T14:32:00.000Z"
},
"insights": {
"riskLevel": "alto",
"riskReasons": [
"string"
],
"addressValidated": false,
"merchantTags": [
"string"
],
"origin": "string",
"buyerHistory": {
"total": 0,
"delivered": 0,
"returned": 0,
"deliveryRate": 0
},
"coverageCod": false,
"carrierName": "Servientrega",
"cityName": "Bogotá"
}
}idstringshopifyOrderIdstringexternalIdstringexternalSourcestringorderNumberstringstatusstringcustomerNamestringcustomerPhonestringcustomerCitystringtotalPricenumberitemsSummarystringlogisticStatusstringEstado logístico TAL CUAL lo reporta el canal del comercio — es texto libre, NO un enumerado cerrado. Cada integración usa su propio vocabulario: ChateaPro manda mayúsculas en español (`PENDIENTE CONFIRMACION`, `NOVEDAD`, `ENTREGADO`, `EN REPARTO`, `RECLAME EN OFICINA`, `GUIA_GENERADA`, `DEVOLUCION`, `CANCELADO`…) y Dropi manda las cadenas de su transportadora. Medido en producción: 41 valores distintos en ChateaPro, 57 en Dropi y 82 en Shopify. NO compares por igualdad contra una lista fija: normaliza (mayúsculas, sin tildes) y compara por palabra clave, o usa `status` (el estado del pedido, que sí es acotado).
trackingNumberstringcarrierstringcallAttemptsintegercityFinalstringprovinceFinalstringconfirmationChannelstringQuién confirmó: call | whatsapp | cross_integration.
attentionReasonstringconfirmedAtstring (date-time)createdAtstring (date-time)
OrderDetailDetalle de un pedido. La forma DIFIERE de la del listado: aquí el cliente y la dirección vienen anidados, y los productos se llaman `products` (no `itemsSummary`).
{
"id": "ord_a1b2c3",
"shopifyOrderId": "5891234567890",
"externalId": "MI-PEDIDO-001",
"externalSource": "string",
"orderNumber": "1042",
"status": "confirmed",
"customer": {
"name": "María González",
"phone": "+573001234567",
"city": "Bogotá"
},
"products": "1x Faja Reductora Talla M",
"totalPrice": 0,
"currency": "COP",
"address": {
"address1": "Calle 40 # 18-08",
"address2": "Calle 40 # 18-08",
"city": "Bogotá",
"province": "Cundinamarca"
},
"addressFinal": "Calle 40 # 18-08",
"cityFinal": "Bogotá",
"provinceFinal": "Cundinamarca",
"logisticStatus": "string",
"trackingNumber": "ABC123456789",
"carrier": "Servientrega",
"logistics": {
"carrier": "Servientrega",
"trackingNumber": "ABC123456789",
"logisticStatus": "string",
"noveltyText": "string",
"lastIncidenceAt": "2026-09-09T14:32:00.000Z"
},
"insights": {
"riskLevel": "alto",
"riskReasons": [
"string"
],
"addressValidated": false,
"merchantTags": [
"string"
],
"origin": "string",
"buyerHistory": {
"total": 0,
"delivered": 0,
"returned": 0,
"deliveryRate": 0
},
"coverageCod": false,
"carrierName": "Servientrega",
"cityName": "Bogotá"
},
"callAttempts": 0,
"confirmationChannel": "string",
"attentionReason": "string",
"confirmedAt": "2026-09-09T14:32:00.000Z",
"createdAt": "2026-09-09T14:32:00.000Z",
"metadata": {},
"calls": [
{
"id": "ord_a1b2c3",
"callType": "string",
"status": "confirmed",
"outcome": "confirmed",
"providerCallId": "id_3f9b02",
"durationSeconds": 0,
"summary": "El cliente confirmó el pedido y la dirección.",
"notesForHuman": "string",
"cancelReason": "string",
"resolutionInstruction": "string",
"channel": "ai",
"human": {
"advisor": {
"id": "ord_a1b2c3",
"name": "María González"
},
"dialedPhone": "+573001234567",
"label": "string"
},
"analysis": {
"sentiment": "string",
"wrongNumber": false,
"addressChanged": false,
"productConfirmed": false,
"priceConfirmed": false
},
"offer": {
"shown": false,
"accepted": false,
"productTitle": "string"
},
"disconnectionReason": "string",
"fromNumber": "string",
"createdAt": "2026-09-09T14:32:00.000Z",
"transcript": "string",
"recordingUrl": "https://…"
}
]
}idstringshopifyOrderIdstringexternalIdstringexternalSourcestringorderNumberstringstatusstringcustomerobjectCliente. En el LISTADO estos mismos datos vienen planos (`customerName`, `customerPhone`, `customerCity`).
- └
namestring - └
phonestring - └
citystring productsstringResumen de productos. En el listado se llama `itemsSummary`.
totalPricenumbercurrencystringMoneda del país de la tienda (COP, MXN, PEN…).
addressobject- └
address1string - └
address2string - └
citystring - └
provincestring addressFinalstringDirección corregida durante la llamada, si el cliente la cambió.
cityFinalstringprovinceFinalstringlogisticStatusstringTexto libre del canal — ver la nota en `Order.logisticStatus`.
trackingNumberstringcarrierstringcallAttemptsintegerconfirmationChannelstringQuién confirmó: call | whatsapp | cross_integration.
attentionReasonstringconfirmedAtstring (date-time)createdAtstring (date-time)metadataobjectSólo campos propios del comercio (`customVars`, `productDetails`, `productDescription`, `callType`); nunca el blob interno.
LogisticStatusUpdateCuerpo del estado LOGÍSTICO — `PATCH https://api.talkyria.com/api/v1/orders/{id}/status`. Al menos un campo.
{
"logisticStatus": "EN REPARTO",
"trackingNumber": "ABC123456789",
"carrier": "Servientrega"
}logisticStatusstringTexto libre, el vocabulario de tu canal. Ver la nota en `Order.logisticStatus`.
trackingNumberstringcarrierstring
OrderStatusUpdateCuerpo del estado del PEDIDO — `PATCH https://app.talkyria.com/api/v1/orders/{id}/status`. Confirmar o cancelar además detiene los reintentos de llamada.
{
"status": "confirmed",
"notes": "string"
}statusreq"confirmed" | "cancelled" | "needs_attention"notesstringNota libre que queda en el pedido.
Call
{
"id": "ord_a1b2c3",
"callType": "string",
"status": "confirmed",
"outcome": "confirmed",
"providerCallId": "id_3f9b02",
"durationSeconds": 0,
"summary": "El cliente confirmó el pedido y la dirección.",
"notesForHuman": "string",
"cancelReason": "string",
"resolutionInstruction": "string",
"channel": "ai",
"human": {
"advisor": {
"id": "ord_a1b2c3",
"name": "María González"
},
"dialedPhone": "+573001234567",
"label": "string"
},
"analysis": {
"sentiment": "string",
"wrongNumber": false,
"addressChanged": false,
"productConfirmed": false,
"priceConfirmed": false
},
"offer": {
"shown": false,
"accepted": false,
"productTitle": "string"
},
"disconnectionReason": "string",
"fromNumber": "string",
"createdAt": "2026-09-09T14:32:00.000Z",
"transcript": "string",
"recordingUrl": "https://…"
}idstringcallTypestringstatusstringoutcomestringproviderCallIdstringId de la llamada en el motor de voz (útil para cruzar con soporte). `null` cuando no hubo llamada en el motor. El mismo campo llega en el webhook saliente (`call.providerCallId`). Añadido 2026-10-02.
durationSecondsintegersummarystringnotesForHumanstringcancelReasonstringresolutionInstructionstringInstrucción operativa generada por IA (novedades/logística).
channel"ai" | "human"Quién marcó: `ai` = el motor de voz · `human` = una persona del equipo desde el softphone. Ambas conviven en la misma lista; este campo es el que las separa.
humanobjectPresente sólo cuando `channel` = `human` (en `ai` viene `null`). Identifica quién marcó y, si fue una marcación libre, a qué número.
- └
advisorobjectEl asesor que marcó. `null` = la marcó el dueño de la cuenta.
- └
dialedPhonestringMarcación libre: número marcado a mano, sin pedido detrás. `null` cuando la llamada sí tiene pedido.
- └
labelstringEtiqueta que el asesor puso a la marcación libre.
analysisobjectAnálisis post-llamada tipado (allowlisted, no-PII). Lo produce la IA: en llamadas con `channel` = `human` todos sus campos vienen en `null` (no hay análisis de IA en una llamada de asesor).
- └
sentimentstring - └
wrongNumberboolean - └
addressChangedboolean - └
productConfirmedboolean - └
priceConfirmedboolean offerobjectResultado de upsell — solo con scope `offers:read`.
- └
shownboolean - └
acceptedboolean - └
productTitlestring disconnectionReasonstringfromNumberstringcreatedAtstring (date-time)transcriptstringSolo con scope `calls:read:content`.
recordingUrlstringEnlace estable `/rec/<token>`. Solo con scope `calls:read:content`.
OfferResult
{
"id": "ord_a1b2c3",
"callId": "call_9f2e10",
"type": "string",
"name": "María González",
"shown": false,
"accepted": false,
"productTitle": "string",
"discountedPrice": 0,
"quantityAccepted": 0,
"chosenVariantTitle": "string",
"revenueUsd": 0,
"lineItemAddedToShopify": false,
"shopifyError": "string",
"createdAt": "2026-09-09T14:32:00.000Z"
}idstringcallIdstringtypestringupsell | quantity | bundle
namestringshownbooleanacceptedbooleanproductTitlestringdiscountedPricenumberquantityAcceptedintegerchosenVariantTitlestringrevenueUsdnumberRevenue del upsell (GMV del merchant).
lineItemAddedToShopifybooleanshopifyErrorstringcreatedAtstring (date-time)
BulkBatch
{
"id": "ord_a1b2c3",
"status": "confirmed",
"total": 0,
"processed": 0,
"succeeded": 0,
"failed": 0,
"customMotif": "string",
"agentId": "agt_7f3c1d",
"createdAt": "2026-09-09T14:32:00.000Z",
"updatedAt": "2026-09-09T14:32:00.000Z"
}idstringstatusstringpending | in_progress | paused | cancelled | completed
totalintegerprocessedintegersucceededintegerfailedintegercustomMotifstringagentIdstringAgente elegido para todo el lote (null = cada pedido con su agente).
createdAtstring (date-time)updatedAtstring (date-time)
Agent
{
"id": "ord_a1b2c3",
"integration": "shopify",
"type": "string",
"name": "María González",
"triggerStatuses": [
"string"
],
"isActive": false,
"voice": {
"id": "ord_a1b2c3",
"name": "María González",
"language": "string"
},
"voiceReady": false,
"hasCallerNumber": false,
"createdAt": "2026-09-09T14:32:00.000Z"
}idstringintegrationstringtypestringnamestringtriggerStatusesstring[]isActivebooleanvoiceobject- └
idstring - └
namestring - └
languagestring voiceReadybooleanhasCallerNumberbooleancreatedAtstring (date-time)
AgentDetail
{
"id": "ord_a1b2c3",
"integration": "shopify",
"type": "string",
"name": "María González",
"triggerStatuses": [
"string"
],
"isActive": false,
"voice": {
"id": "ord_a1b2c3",
"name": "María González",
"language": "string"
},
"voiceReady": false,
"hasCallerNumber": false,
"createdAt": "2026-09-09T14:32:00.000Z",
"retry": {
"maxRetries": 0,
"delayMinutes": 0
},
"maxCallDuration": 0,
"updatedAt": "2026-09-09T14:32:00.000Z",
"callMode": "AUTO",
"hybridAmountThreshold": 0,
"duplicateCallWindowHours": 0,
"timezone": "string",
"callDelaySeconds": 0
}idstringintegrationstringtypestringnamestringtriggerStatusesstring[]isActivebooleanvoiceobject- └
idstring - └
namestring - └
languagestring voiceReadybooleanhasCallerNumberbooleancreatedAtstring (date-time)retryobject- └
maxRetriesinteger - └
delayMinutesinteger maxCallDurationintegerupdatedAtstring (date-time)callMode"AUTO" | "MANUAL" | "HYBRID"hybridAmountThresholdnumberduplicateCallWindowHoursintegertimezonestringcallDelaySecondsinteger
Voice
{
"voiceId": "9Godp7dNohUvXk6qp0gS",
"name": "María González",
"language": "string",
"accent": "string",
"gender": "string",
"tier": "string",
"isMultilingual": false,
"previewUrl": "https://…"
}voiceIdstringnamestringlanguagestringaccentstringgenderstringtierstringisMultilingualbooleanpreviewUrlstring
PhoneNúmero dedicado (merchant-safe — nunca expone el carrier interno, Regla 119).
{
"id": "ord_a1b2c3",
"phoneNumber": "+16015551234",
"nickname": "string",
"country": "US",
"monthlyPriceUsd": 2,
"isActive": false,
"purchasedAt": "2026-09-09T14:32:00.000Z",
"nextBillingAt": "2026-09-09T14:32:00.000Z"
}idstringphoneNumberstringnicknamestringcountrystringmonthlyPriceUsdnumberisActivebooleanpurchasedAtstring (date-time)nextBillingAtstring (date-time)
VerifiedCallerIdNúmero propio del merchant verificado (Camino 1). Nunca expone el detalle de fallo del proveedor de verificación.
{
"id": "ord_a1b2c3",
"phoneNumber": "+573001234567",
"country": "CO",
"status": "pending",
"verificationMethod": "call",
"verifiedAt": "2026-09-09T14:32:00.000Z",
"lastTestCallAt": "2026-09-09T14:32:00.000Z",
"createdAt": "2026-09-09T14:32:00.000Z"
}idstringphoneNumberstringcountrystringISO 3166-1 alfa-2 derivado del número (p. ej. "CO", "ES").
status"pending" | "verified" | "failed"verificationMethod"call" | "sms"verifiedAtstring (date-time)lastTestCallAtstring (date-time)createdAtstring (date-time)
TriggerRequestDispara 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`.
{
"externalId": "MI-PEDIDO-001",
"callType": "confirmation",
"estado": "string",
"immediate": false,
"scheduledAt": "2026-09-09T14:32:00.000Z",
"timezone": "string",
"language": "string",
"source": "string",
"agentId": "agt_7f3c1d",
"merchantExternalId": "id_3f9b02",
"customer": {
"name": "María González",
"phone": "+573001234567",
"email": "cliente@ejemplo.com",
"ns": "string"
},
"products": [
{
"name": "María González",
"quantity": 1,
"price": "string"
}
],
"totalPrice": "string",
"currency": "COP",
"shippingAddress": {
"address1": "Calle 40 # 18-08",
"address2": "Calle 40 # 18-08",
"city": "Bogotá",
"province": "Cundinamarca",
"countryCode": "CO"
},
"metadata": {},
"customVariables": {
"clave": "string"
}
}externalIdreqstringID del pedido en tu sistema (clave de idempotencia).
callType"confirmation" | "novelty" | "office" | "delivery" | "dispatched" | "delivered" | "devolucion"estadostringOpcional. Estado del pedido EN TU PLATAFORMA ("listo", "empacado", lo que sea). Sin `agentId`, el canal (`source`) + este estado eligen el agente según los disparadores configurados en el Studio. Un estado sin disparador guarda el pedido sin llamada (`not_called`, `no_trigger_configured`).
immediateboolean«Llamar ya»: omite el retardo de primera llamada del agente Y su horario de atención (la llamada sale en ~2 s). NO omite el modo de llamada del agente. Excluyente con `scheduledAt`.
scheduledAtstring (date-time)Llamar en este instante (ISO 8601, futuro, máx. 7 días). Reemplaza el retardo del agente y no se reprograma por su horario; si cae fuera de él, la respuesta lo avisa en `warnings` (`scheduled_outside_agent_hours`). Excluyente con `immediate`. Sin `immediate` ni `scheduledAt`, la llamada hereda el retardo, el horario y la acción fuera de horario del agente.
timezonestringNo es un override: el horario es del agente. Si se envía, se ignora y la respuesta lo indica en `warnings` (`ignored_field:timezone`).
languagestringNo es un override: el idioma es del agente. Si se envía, se ignora y la respuesta lo indica en `warnings` (`ignored_field:language`).
sourcestringDe dónde viene la llamada (ej. tu CRM). Opcional; default `api`. También aceptado como `metadata.source`.
agentIdstringEnlace explícito de agente ("trigger custom"): marca ESTE agente para esta llamada. REQUERIDO para agentes API-native (type="api", sin ruteo por estado); opcional para agentes de integración — cuando se omite, aplica el ruteo por estado. Debe ser un agente ACTIVO de tu cuenta (si no, responde 400 agent_not_found).
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).
currencystringshippingAddressobject- └
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}}`.
TriggerResponse
{
"success": true,
"orderId": "id_3f9b02",
"callId": "call_9f2e10",
"status": "queued",
"notCalledReason": "string",
"message": "string",
"schedule": {
"firstCallAt": "2026-09-09T14:32:00.000Z",
"source": "request_immediate",
"delaySeconds": 0,
"deferredToWindow": false,
"agentId": "agt_7f3c1d",
"triggerId": "id_3f9b02"
},
"callMode": {
"agent": "string",
"applied": false,
"reason": "string"
},
"warnings": [
"string"
]
}successbooleanorderIdstringcallIdstringstatusstring`queued` | `not_called` | `paused`.
notCalledReasonstringSolo con `status: not_called`.
messagestringscheduleobjectPlan de la primera llamada (aditivo).
- └
firstCallAtstring (date-time) - └
source"request_immediate" | "request_scheduled" | "trigger" | "agent" | "settings" | "off_hours"De dónde salió el momento de la llamada. `off_hours` = movida a la próxima franja del agente.
- └
delaySecondsintegerRetardo heredado (o pedido) antes de pisos y horario.
- └
deferredToWindowboolean - └
agentIdstring - └
triggerIdstring callModeobjectModo de llamada del agente aplicado a esta llamada (aditivo).
- └
agentstring - └
appliedboolean - └
reasonstring warningsstring[]`ignored_field:timezone`, `ignored_field:language`, `scheduled_outside_agent_hours`.
CreateAgentRequestCrear un agente. `integration` selecciona el tipo; omitirlo lo resuelve el motor del workspace. Campos requeridos adicionales por integración: **universal** → `mission` (define qué atiende el agente y le siembra sus disparadores); **shopify** → `type`; **chateapro/dropi** → `triggerStatuses` (+ `triggerCallType` obligatorio en chateapro); **sales** → `productName`, `productPrice`, `currency`, `paymentType`. Campos no aplicables a la integración se ignoran.
{
"integration": "universal",
"mission": "confirmation_cod",
"name": "María González",
"type": "confirmation",
"triggerCallType": "confirmation",
"description": "string",
"triggerStatuses": [
"string"
],
"voiceId": "9Godp7dNohUvXk6qp0gS",
"language": "string",
"allowUnverifiedVoice": false,
"maxRetries": 0,
"retryDelayMinutes": 0,
"maxCallDuration": 0,
"callDelaySeconds": 0,
"phoneNumberId": "+573001234567",
"enableVoicemailDetection": false,
"customPrompt": "string",
"useCustomPrompt": false,
"workingHours": {
"respect": false,
"start": "string",
"end": "string",
"days": [
0
],
"timezone": "string",
"offHoursAction": "string"
},
"callMode": "AUTO",
"duplicateMode": "WINDOW",
"discountEnabled": false,
"discountCode": "string",
"discountType": "percent",
"discountValue": 0,
"productName": "1x Faja Reductora Talla M",
"productPrice": "string",
"currency": "COP",
"paymentType": "string",
"productDetails": "string",
"quantityOfferEnabled": false,
"upsellEnabled": false,
"objections": "string"
}integration"universal" | "shopify" | "chateapro" | "dropi" | "sales"Omitida → la resuelve el MOTOR del workspace (universal si ya migró; shopify si es legado). NUNCA declarar un default estático: un cliente generado que lo inyecte explícito recibiría 409 wrong_engine en workspaces universales (Regla 502).
mission"confirmation_cod" | "confirmation_prepaid" | "dispatch" | "novelty" | "office_pickup" | "delivery_upcoming" | "delivery_attempt" | "post_delivery" | "returns_recovery" | "cancelled_winback" | "telemarketing" | "cart_recovery" | "sales" | "custom"universal — vocación del agente. De ella salen su flujo canónico y sus disparadores. OBLIGATORIA para `universal`: omitirla responde 400 (un agente sin misión nacería sin disparadores y no recibiría pedidos). Las 14 vocaciones: `confirmation_cod` (confirmar contraentrega), `confirmation_prepaid` (confirmar prepagado), `dispatch` (aviso de despacho), `novelty` (resolver novedades logísticas), `office_pickup` (recoger en oficina), `delivery_upcoming` (entrega próxima), `delivery_attempt` (intento de entrega), `post_delivery` (posventa), `returns_recovery` (recuperar devoluciones), `cancelled_winback` (recuperar cancelados), `telemarketing`, `cart_recovery` (carritos abandonados), `sales` (venta en frío) y `custom` (flujo propio).
namereqstringtype"confirmation" | "cart_recovery" | "prepaid" | "dispatch_cod" | "dispatch_prepaid" | "custom" | "api"Solo shopify. `api` = agente API-native (integration-neutral, sin ruteo por estado): se marca únicamente con el `agentId` explícito de POST /calls/trigger. Ilimitados por cuenta.
triggerCallType"confirmation" | "novelty" | "office" | "delivery" | "dispatched" | "delivered" | "devolucion"chateapro (obligatorio) / dropi.
descriptionstringtriggerStatusesstring[]shopify / chateapro / dropi.
voiceIdstringlanguagestringallowUnverifiedVoicebooleanCon `voiceId`: el servidor rechaza con `422 voice_language_mismatch` una voz que el catálogo PRUEBA ajena al idioma del agente (ni nativa ni verificada para él). `true` la acepta igualmente — la misma libertad que da el panel.
maxRetriesintegerretryDelayMinutesintegermaxCallDurationintegercallDelaySecondsintegerphoneNumberIdstringenableVoicemailDetectionbooleancustomPromptstringuseCustomPromptbooleanworkingHoursobject- └
respectboolean - └
startstring - └
endstring - └
daysinteger[] - └
timezonestring - └
offHoursActionstring callMode"AUTO" | "MANUAL"Solo dropi.
duplicateMode"WINDOW" | "OFF"Solo dropi.
discountEnabledbooleandiscountCodestringdiscountType"percent" | "fixed"discountValuenumberproductNamestringSolo sales (requerido).
productPricestringSolo sales (requerido).
currencystringSolo sales (requerido).
paymentTypestringSolo sales (requerido).
productDetailsstringquantityOfferEnabledbooleanupsellEnabledbooleanobjectionsstring
UpdateAgentRequestTodos 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`, …).
{
"integration": "string",
"triggerCallType": "confirmation",
"name": "María González",
"description": "string",
"triggerStatuses": [
"string"
],
"voiceId": "9Godp7dNohUvXk6qp0gS",
"language": "string",
"allowUnverifiedVoice": false,
"customPrompt": "string",
"useCustomPrompt": false,
"maxRetries": 0,
"retryDelayMinutes": 0,
"retryScheduleJson": "string",
"maxCallDuration": 0,
"callDelaySeconds": 0,
"callMode": "string",
"hybridAmountThreshold": 0,
"phoneNumberId": "+573001234567",
"verifiedCallerIdId": "id_3f9b02",
"isActive": false,
"enableVoicemailDetection": false,
"duplicateMode": "string",
"duplicateCallWindowHours": 0,
"discountEnabled": false,
"discountCode": "string",
"discountType": "string",
"discountValue": 0,
"workingHours": {
"respect": false,
"start": "string",
"end": "string",
"days": [
0
],
"timezone": "string",
"offHoursAction": "string"
},
"retryHours": {
"respect": false,
"start": "string",
"end": "string",
"days": "string"
}
}integrationstringIgnorado — la integración se resuelve por el id.
triggerCallType"confirmation" | "novelty" | "office" | "delivery" | "dispatched" | "delivered" | "devolucion"chateapro/dropi.
namestringdescriptionstringtriggerStatusesstring[]voiceIdstringlanguagestringallowUnverifiedVoicebooleanCon `voiceId`: el servidor rechaza con `422 voice_language_mismatch` una voz que el catálogo PRUEBA ajena al idioma del agente (ni nativa ni verificada para él). `true` la acepta igualmente — la misma libertad que da el panel.
customPromptstringuseCustomPromptbooleanmaxRetriesintegerretryDelayMinutesintegerretryScheduleJsonstringmaxCallDurationintegercallDelaySecondsintegercallModestring**universal**: `AUTO` | `MANUAL` | `HYBRID` — el modo que respetan TODAS las llamadas del agente, también las creadas por API. **dropi**: `AUTO` | `MANUAL`.
hybridAmountThresholdnumberuniversal: con `HYBRID`, solo se llama sola a los pedidos por DEBAJO de este monto. Un valor ≤ 0 se guarda como null (se llama todo), igual que en el Studio.
phoneNumberIdstringverifiedCallerIdIdstringisActivebooleanenableVoicemailDetectionbooleanduplicateModestringduplicateCallWindowHoursintegerdiscountEnabledbooleandiscountCodestringdiscountTypestringdiscountValuenumberworkingHoursobject- └
respectboolean - └
startstring - └
endstring - └
daysinteger[] - └
timezonestring - └
offHoursActionstring retryHoursobject- └
respectboolean - └
startstring - └
endstring - └
daysstring | integer[]CSV o array de días.
WorkflowDefinitionGrafo del flujo conversacional. El motor valida invariantes al guardar.
{
"nodes": [
{
"id": "ord_a1b2c3",
"type": "startCall",
"position": {},
"data": {}
}
],
"edges": [
{
"id": "ord_a1b2c3",
"source": "string",
"target": "string",
"data": {
"label": "string",
"condition": "string"
}
}
],
"global_node_id": "string"
}nodesreqobject[]- └
idstring - └
typestring - └
positionobject - └
dataobject edgesobject[]- └
idstring - └
sourcestring - └
targetstring - └
dataobject global_node_idstring
AdvancedConfigConfiguración avanzada del agente. En PATCH todos los campos son opcionales (los omitidos se preservan).
{
"ring_duration_ms": 0,
"max_call_duration_ms": 0,
"end_call_after_silence_ms": 0,
"enable_backchannel": false,
"voicemail": {
"enabled": false,
"action": "hangup",
"speech_cutoff_seconds": 0,
"system_prompt": "string"
},
"dictionary": [
{
"phrase": "string",
"boost": 0,
"phonetic": "+573001234567"
}
],
"analysis_fields": [
{
"type": "boolean",
"name": "María González",
"description": "string",
"choices": [
"string"
]
}
],
"handbook": {
"default_personality": false,
"natural_filler_words": false,
"high_empathy": false,
"echo_verification": false,
"nato_phonetic_alphabet": false,
"speech_normalization": false,
"smart_matching": false,
"ai_disclosure": false,
"scope_boundaries": false
}
}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
WebhookEndpointUn webhook saliente registrado. El `secret` NUNCA se incluye aquí.
{
"id": "ord_a1b2c3",
"url": "https://…",
"events": "call.outcome_final",
"isActive": false,
"merchantExternalId": "id_3f9b02",
"createdAt": "2026-09-09T14:32:00.000Z"
}idstringurlstring (uri)eventsstringEventos suscritos, separados por coma (Regla 421). `call.outcome_final` = todos los resultados de llamada; o granulares `call.confirmed`/`call.cancelled`/`call.no_answer`/`call.voicemail`/`call.novelty`/`call.needs_attention`/`call.failed`. `call.novelty_resolved` (novedad resuelta por la IA o por Dropi; payload con `novelty` en vez de `call`) solo llega si se lista explícitamente o con `*`.
isActivebooleanmerchantExternalIdstringcreatedAtstring (date-time)
WebhookEndpointWithSecretWebhook con el `secret` incluido — devuelto SOLO al crearlo o al regenerarlo (una vez).
{
"id": "ord_a1b2c3",
"url": "https://…",
"events": "call.outcome_final",
"isActive": false,
"merchantExternalId": "id_3f9b02",
"createdAt": "2026-09-09T14:32:00.000Z"
}idstringurlstring (uri)eventsstringEventos suscritos, separados por coma (Regla 421). `call.outcome_final` = todos los resultados de llamada; o granulares `call.confirmed`/`call.cancelled`/`call.no_answer`/`call.voicemail`/`call.novelty`/`call.needs_attention`/`call.failed`. `call.novelty_resolved` (novedad resuelta por la IA o por Dropi; payload con `novelty` en vez de `call`) solo llega si se lista explícitamente o con `*`.
isActivebooleanmerchantExternalIdstringcreatedAtstring (date-time)