API Reference

Endpoints REST públicos de IxiChat. Base URL: https://ixichat.com. Todos los endpoints bajo /api/v1 requieren bearer auth con un api_key (formato ixc_live_*).

Si todavía no tenés un api_key, leé primero el flujo OAuth. Para llamadas server-to- server de uso interno también se puede crear un api_key manual desde /app/settings/api-keys.

Autenticación

Bearer en el header Authorization:

text
Authorization: Bearer ixc_live_<32-chars>

Cada llamada actualiza api_keys.last_used_at para que el dueño del workspace vea qué tokens están activos.

Rate limiting

  • Per-key: 200 req/min sostenido con burst de 200.
  • Per-tenant: 800 req/min agregado (defensa contra crear N keys para multiplicar).
  • Cuando se excede: HTTP 429 con headers X-RateLimit-Remaining y Retry-After.

Endpoints

Mensajería

POST/api/v1/messages

Enviar un mensaje a un contacto. Scope: messages.send.

bash
curl -X POST https://ixichat.com/api/v1/messages \
  -H "Authorization: Bearer ixc_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "channel_id": "uuid-del-canal",
    "contact_phone": "18091234567",
    "text": "Hola, somos del equipo de MiClinica. Tu cita es mañana 10am."
  }'

Crea el contacto si no existe. Devuelve { message_id, conversation_id }.

Contactos

GET/api/v1/contacts

Lista contactos del tenant. Scope: read. Query params: limit (default 50, max 200), cursor.

POST/api/v1/contacts

Crear contacto. Scope: contacts.write.

json
{
  "phone": "18091234567",
  "name": "Manuel Valenzuela",
  "email": "manuel@example.com",
  "metadata": { "patient_id": "P-9982" }
}

Conversaciones

GET/api/v1/conversations

Lista de conversaciones. Filtros: status, channel_id, contact_id.

GET/api/v1/conversations/[id]

Detalle de conversación + últimos mensajes. Scope: read.

PATCH/api/v1/conversations/[id]

Cambiar status (open/pending/resolved/snoozed) o asignación. Scope: conversations.write.

Flujos

POST/api/v1/flows/[slug]/start

Disparar un flujo automatizado para un contacto. Scope: flows.run.

json
{ "contact_id": "uuid", "variables": { "cita_fecha": "2026-06-01" } }

Sandbox keys

Para probar tu integración sin disparar mensajes reales a clientes, generá una sandbox key. Las identificás por el prefijo:

  • ixc_live_* — production. Cualquier envío llama a Meta / WhatsApp / Baileys de verdad.
  • ixc_test_* — sandbox. Los endpoints side-effecting (POST /api/v1/messages, POST /api/embed/send) NO llaman APIs externas. El mensaje queda persistido con metadata.sandbox = true y un message_id con prefijo sandbox-… — el dev lo ve en el inbox interno sin spamear al cliente real.

Cómo generarla: en el workspace que vas a usar para testing, andá a /app/settings/api-keys → "Nueva API key", marcá Sandbox (test key), asignale los scopes que necesitás. El plaintext queda visible una sola vez.

Patrón Stripe

Prefijos distintos previenen que mezcles credenciales por accidente (e.g. test key en prod, o viceversa). Sumá un check en tu CI: en producción, las keys deben empezar con ixc_live_.

Errors

Forma estándar:

json
{ "error": "rate_limited", "detail": "200 req/min exceeded", "retry_after": 30 }
StatusSignificado
400Body inválido o campos requeridos faltantes.
401API key inválida, revocada o expirada.
403Scope insuficiente para esta operación.
404Recurso no encontrado (o no en tu tenant).
410Recurso existió pero fue borrado/cancelado.
429Rate limit excedido. Mira Retry-After.
5xxProblema nuestro. Reintenta con backoff exponencial.

Idempotency

Para POSTs que crean recursos, pasá un header Idempotency-Key con un UUID v4. Si repetís la misma request con la misma key dentro de 24h te devolvemos la misma respuesta sin crear duplicado.