API de Talkyria v1

Integra Talkyria con tu plataforma para automatizar llamadas de confirmacion de pedidos COD. Consulta ordenes, dispara llamadas, recibe webhooks con el resultado.

Introduccion

Base URL

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

Autenticacion

Bearer token

Rate limit

60 req/min

Formato

JSON

GET/orders/:idConsultar orden con llamadas
GET/orders?phone=XBuscar ordenes
POST/calls/triggerDisparar llamada
PATCH/orders/:id/statusActualizar estado logistico

Autenticacion

Todas las requests requieren un API key en el header Authorization. Genera tu key en app.talkyria.com → Vinculacion → API.

curl -H "Authorization: Bearer tk_live_abc123def456..." \
  https://api.talkyria.com/api/v1/orders

Ordenes

Consultar orden

GET/api/v1/orders/:id

Retorna la orden con todas sus llamadas asociadas.

// Response
{
  "id": "cmmut6in0009...",
  "shopifyOrderId": "6789012345",
  "externalId": "chateapro_123",
  "orderNumber": "#1234",
  "status": "confirmed",
  "customer": {
    "name": "Juan Perez",
    "phone": "+573001234567",
    "city": "Bogota"
  },
  "products": "Samsung Galaxy S25 x1",
  "totalPrice": 85600,
  "address": {
    "address1": "Calle 45 #23-12",
    "city": "Bogota",
    "province": "Cundinamarca"
  },
  "addressFinal": "Calle 45 #23-12, Apto 301",
  "callAttempts": 2,
  "confirmedAt": "2026-03-17T21:00:00Z",
  "calls": [
    {
      "id": "call_log_id",
      "callType": "confirmation",
      "outcome": "confirmed",
      "durationSeconds": 87,
      "recordingUrl": "https://...",
      "transcript": "Hola, hablo con Juan?...",
      "summary": "El agente confirmo el pedido...",
      "createdAt": "2026-03-17T20:58:00Z"
    }
  ]
}

Buscar ordenes

GET/api/v1/orders

Busca ordenes por telefono, ID externo, o ID de Shopify.

ParametroTipoDescripcion
phonestringTelefono E.164 (+573001234567)
externalIdstringID de tu plataforma
shopifyOrderIdstringID de orden Shopify
limitnumberMax resultados (default 50, max 100)
offsetnumberPaginacion

Disparar llamada

POST/api/v1/calls/trigger

Crea una orden y encola una llamada de confirmacion. Usa los mismos billing guards, working hours y deduplicacion que las llamadas de Shopify.

// Request
curl -X POST \
  -H "Authorization: Bearer tk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "chateapro",
    "callType": "confirmation",
    "customer": {
      "name": "Juan Perez",
      "phone": "+573001234567",
      "ns": "contact_123",
      "city": "Bogota"
    },
    "address": {
      "address1": "Calle 45 #23-12",
      "address2": "Apto 301",
      "city": "Bogota",
      "province": "Cundinamarca"
    },
    "order": {
      "externalId": "CP-12345",
      "products": "Samsung Galaxy S25 x1",
      "totalPrice": 85600,
      "currency": "COP"
    }
  }' \
  https://app.talkyria.com/api/v1/calls/trigger

// Response (200)
{
  "success": true,
  "orderId": "cmmxyz...",
  "callId": "cmmyyy...",
  "message": "Llamada encolada exitosamente",
  "estimatedCallTime": "< 30 segundos"
}
CampoRequeridoDescripcion
sourceSiOrigen: "chateapro", "dropi", "api"
callTypeSi"confirmation" | "novelty" | "office"
customer.nameSiNombre completo del cliente
customer.phoneSiTelefono E.164 (+573001234567)
customer.nsNoNS del contacto (ChateaPro) — se devuelve en webhook
order.externalIdSiID unico del pedido en tu plataforma
order.productsSiProductos como texto: "Gel x1"
order.totalPriceSiValor total (numero): 72990
order.currencySiMoneda: COP, MXN, USD
address.address1SiDireccion principal
address.citySiCiudad de entrega
productsSiArray de productos
totalPriceSiTotal como string
shippingAddressNoDireccion de envio
metadataNoDatos extra (JSON libre)

Actualizar estado logistico

PATCH/api/v1/orders/:id/status
curl -X PATCH \
  -H "Authorization: Bearer tk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "logisticStatus": "shipped", "trackingNumber": "CR123456789", "carrier": "InterRapidisimo" }' \
  https://api.talkyria.com/api/v1/orders/cmmxyz.../status
logisticStatusDescripcion
processingEn preparacion
shippedDespachado
in_transitEn transito
deliveredEntregado
returnedDevuelto
failed_deliveryEntrega fallida

Webhooks

Recibe un POST cuando Talkyria determina el resultado final de una llamada. Configura tu webhook en app.talkyria.com → Vinculacion → API.

Evento: call.outcome_final

Se dispara UNA vez por orden cuando el outcome final se determina. No se envia en reintentos intermedios.

// Payload enviado a tu webhook URL
{
  "event": "call.outcome_final",
  "timestamp": "2026-03-17T21:00:00Z",
  "order": {
    "id": "cmmut6in...",
    "externalId": "chateapro_123",
    "orderNumber": "#1234",
    "status": "confirmed",
    "products": "Samsung Galaxy S25 x1",
    "totalPrice": "85600",
    "customer": { "name": "Juan", "phone": "+573001234567" },
    "address": { "address1": "Calle 45 #23-12", "city": "Bogota" }
  },
  "call": {
    "id": "call_log_id",
    "outcomeFinal": "confirmed",
    "durationSeconds": 87,
    "recordingUrl": "https://...",
    "transcript": "...",
    "summary": "..."
  },
  "shop": { "domain": "mitienda.myshopify.com", "country": "CO" }
}

Verificar firma HMAC

Cada webhook incluye X-Talkyria-Signature: sha256=xxx. Verifica la firma con tu secret.

Node.js

const crypto = require("crypto");

function verifySignature(body, signature, secret) {
  const expected = "sha256=" + crypto
    .createHmac("sha256", secret)
    .update(body)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Python

import hmac, hashlib

def verify_signature(body: str, signature: str, secret: str) -> bool:
    expected = "sha256=" + hmac.new(
        secret.encode(), body.encode(), hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(signature, expected)

Reintentos: 3 intentos con backoff (1 min, 5 min, 30 min).

Outcomes

OutcomeDescripcion
confirmedPedido confirmado por el cliente
cancelledPedido cancelado por el cliente
no_answerCliente no contesto despues de todos los reintentos
novedadRequiere revision manual (direccion incorrecta, etc.)
recoveredCarrito abandonado recuperado
not_recoveredCarrito abandonado no recuperado

Errores

CodigoDescripcion
401API key invalida o faltante
400Datos invalidos (ver mensaje de error)
404Orden no encontrada
405Metodo HTTP no permitido
429Rate limit excedido (60 req/min)
500Error interno del servidor
// Error response format
{ "error": "Descripcion del error" }

Ejemplos completos

JavaScript (fetch)

const API_KEY = "tk_live_abc123...";
const BASE = "https://api.talkyria.com/api/v1";

// Disparar llamada
const res = await fetch(`${BASE}/calls/trigger`, {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    externalId: "mi_orden_123",
    customer: { name: "Juan", phone: "+573001234567" },
    products: [{ name: "Producto X", quantity: 1 }],
    totalPrice: "85600",
  }),
});
const data = await res.json();
console.log(data.orderId, data.status);

// Consultar resultado
const order = await fetch(`${BASE}/orders/${data.orderId}`, {
  headers: { "Authorization": `Bearer ${API_KEY}` },
}).then(r => r.json());
console.log(order.calls[0]?.outcome);

Python (requests)

import requests

API_KEY = "tk_live_abc123..."
BASE = "https://api.talkyria.com/api/v1"
headers = {"Authorization": f"Bearer {API_KEY}"}

# Disparar llamada
res = requests.post(f"{BASE}/calls/trigger", headers=headers, json={
    "externalId": "mi_orden_123",
    "customer": {"name": "Juan", "phone": "+573001234567"},
    "products": [{"name": "Producto X", "quantity": 1}],
    "totalPrice": "85600",
})
data = res.json()
print(data["orderId"], data["status"])

# Consultar resultado
order = requests.get(f"{BASE}/orders/{data['orderId']}", headers=headers).json()
print(order["calls"][0]["outcome"])

Talkyria API v1 — Confirma pedidos COD con IA

Preguntas? contacto@talkyria.com