Introducción
Esta referencia describe la API de Sofia Chat para operar campañas de WhatsApp de punta a punta: gestión de contactos y grupos, plantillas aprobadas por Meta, creación y envío de campañas, y seguimiento del estado de entrega de cada mensaje — todo vía API, sin necesidad de ingresar al panel.
Todos los endpoints están bajo la URL base de producción y requieren autenticación, salvo el inicio de sesión. Las operaciones actúan únicamente sobre los datos de su organización.
Flujo de integración
- Autentíquese y obtenga su token.
- Descubra sus recursos: organización, canal de WhatsApp, plantillas y etiquetas.
- Cargue destinatarios: contactos y grupos, individual o por Excel.
- Cree y envíe la campaña; consulte el avance por destinatario.
https://api-v2.sofiachat.com
# Obtenga su token y llame la API curl -X POST \ https://api-v2.sofiachat.com/api/auth/log-in \ -H "Content-Type: application/json" \ -d '{"email":"api@su-empresa.com", "password":"***"}'
Requisito previo
- Plantilla aprobada: toda campaña que inicia una conversación requiere una plantilla en estado
approved(política de Meta; la aprobación toma hasta 24 horas). - Rol Owner o Admin: los módulos de contactos, plantillas y campañas requieren estos roles en la organización.
Convenciones
- Prefijo
/apien todas las rutas. - Mutaciones vía POST con sub-ruta semántica (
/update,/delete,/opt-out…). La API no acepta PATCH, PUT ni DELETE en estos módulos. - Respuesta estándar
{ "ok": true, ... }; listados paginados:{ ok, data, total, page, pageSize }. - Fechas ISO 8601 en UTC. Teléfonos en formato internacional, solo dígitos, 8–15 (ej. Guatemala:
50255551234).
Códigos de error
| Código | Significado |
|---|---|
| 400 | Solicitud inválida — revise el cuerpo. |
| 401 | Token vencido o inválido — vuelva a autenticarse. |
| 403 | El rol no tiene permiso sobre el módulo. |
| 404 | Recurso inexistente o de otra organización. |
| 5xx | Error del servidor — reintente con espera exponencial. |
{
"ok": true,
"data": [ … ],
"total": 120,
"page": 1,
"pageSize": 20
}
Iniciar sesión
Obtiene el token de acceso (JWT) con las credenciales de su cuenta. Incluya el token en el encabezado Authorization: Bearer {token} de todas las llamadas siguientes.
El token tiene vigencia limitada: ante un 401, vuelva a autenticarse y reintente. Recomendamos automatizar la renovación.
curl -X POST \ https://api-v2.sofiachat.com/api/auth/log-in \ -H "Content-Type: application/json" \ -d '{"email":"api@su-empresa.com", "password":"********"}'
{
"ok": true,
"token": "eyJhbGciOi...",
"refreshToken": "9f3c1a7b-..."
}
Mis organizaciones
Devuelve las organizaciones del usuario autenticado. El campo organizationId es el {orgId} que usará en todas las demás rutas.
{
"ok": true,
"organizations": [
{
"role": "owner",
"organizationId": 7,
"organization": {
"id": 7,
"name": "Su Empresa"
}
}
]
}
Canales de WhatsApp
Devuelve los departamentos de su organización con sus canales. El id del canal de tipo whatsapp es el integrationId que se usa en plantillas y campañas.
[
{
"id": 3,
"name": "Ventas",
"channels": [
{
"id": 11,
"type": "whatsapp",
"status": "active"
}
]
}
]
Etiquetas de conversación
Devuelve las etiquetas de su organización. Las conversaciones generadas por una campaña quedan clasificadas bajo la etiqueta indicada al crearla (conversationTagId), visibles para su equipo en el panel de Sofia Chat.
{
"ok": true,
"tags": [
{
"id": 14,
"name": "Prioridad alta",
"color": "#FF5733"
}
]
}
Listar contactos
Listado paginado de los contactos de la organización, con filtros de búsqueda. El detalle de un contacto se obtiene con GET /api/contact/{orgId}/{id}.
{
"ok": true,
"data": [
{
"id": 501,
"phone": "+50255551234",
"first_name": "Ana",
"last_name": "López",
"email": "ana@ejemplo.com",
"custom_fields": { "ciudad": "Guatemala" },
"opt_out_at": null
}
],
"total": 1, "page": 1, "pageSize": 20
}
Crear contacto
400.{"ciudad": "Guatemala"}). Defina las claves primero en Campos personalizados; luego puede usarlas para personalizar mensajes de campaña.curl -X POST \
https://api-v2.sofiachat.com/api/contact/{orgId} \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"phone": "50255551234",
"firstName": "María",
"customFields": { "ciudad": "Guatemala" }
}'
Actualizar y eliminar
Actualiza los datos de un contacto (mismo cuerpo que la creación; los campos omitidos no cambian) o lo elimina. Recuerde: todas las mutaciones son POST con sub-ruta; PATCH/PUT/DELETE no son aceptados.
Bajas de comunicación (opt-out / opt-in)
Da de baja a un contacto de las campañas, o lo reactiva. Un contacto con opt-out queda excluido automáticamente de toda campaña — aparece como skipped entre los destinatarios aunque esté en el grupo enviado — conforme a las políticas de Meta. Este estado no puede sobrescribirse mediante la importación de Excel.
curl -X POST \
https://api-v2.sofiachat.com\
/api/contact/{orgId}/{id}/opt-out \
-H "Authorization: Bearer {token}"
Listar grupos
Devuelve los grupos de la organización con su conteo de miembros. Los grupos son la forma recomendada de dirigir campañas: segmentos reutilizables a los que apunta con su groupId.
{
"ok": true,
"groups": [
{
"id": 12,
"name": "Clientes VIP",
"description": "Compras > $1000",
"memberCount": 34
}
]
}
Crear y administrar grupos
Crea un grupo con { "name": "...", "description": "..." }, actualiza sus datos o lo elimina.
Miembros del grupo
curl -X POST \
https://api-v2.sofiachat.com\
/api/contact-group/{orgId}/{id}/add-contacts \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{"contactIds":[501,502]}'
Campos personalizados
Define los atributos propios de su negocio (ciudad, empresa, número de póliza…). Una vez definidos, las claves quedan disponibles como columnas en la importación por Excel, en customFields de cada contacto, y como custom_fields.<clave> en la personalización de mensajes de campaña.
Descargar plantilla de importación
Descarga un archivo .xlsx con los encabezados correctos — phone, first_name, last_name, email, más una columna por cada campo personalizado definido — y una fila de ejemplo. Úselo como base para preparar sus datos.
Validar archivo (preview)
Valida el archivo sin escribir nada en la base (dry run). Envíe el archivo como multipart/form-data en el campo file. Límite: 5,000 filas por archivo.
phonees la única columna obligatoria; filas sin teléfono válido se marcan como inválidas.- Detecta duplicados dentro del archivo y contra la base.
- Columnas que coinciden con un campo personalizado se asignan a
customFields; las desconocidas se ignoran.
{
"totalRows": 1250,
"valid": 1180,
"invalid": 40,
"duplicatesInFile": 10,
"duplicatesInDb": 20,
"rows": [
{
"rowNumber": 2,
"phone": "50255551234",
"status": "new"
}
]
}
Confirmar importación
Ejecuta la importación. Envíe el archivo (multipart, campo file) junto con las opciones:
true los duplicados se actualizan; con false se omiten.{
"created": 1150,
"updated": 20,
"skipped": 10,
"failed": 0
}
Exportar contactos
Exporta los contactos de la organización a .xlsx, con filtros opcionales por grupo y por estado de opt-out. Útil para auditoría y respaldo.
Listar plantillas
Devuelve las plantillas de la organización, con filtro opcional por canal. Solo las plantillas en estado approved pueden usarse en campañas. Las variables del mensaje ({{1}}, {{2}}…) están en el componente BODY.
El detalle individual se obtiene con GET /api/template/{orgId}/{id}.
{
"ok": true,
"templates": [
{
"id": 88,
"integration_id": 11,
"name": "recordatorio_cita",
"language": "es_MX",
"category": "utility",
"status": "approved",
"components": [
{
"type": "BODY",
"text": "Hola {{1}}, tu cita es el {{2}}"
}
]
}
]
}
Sincronizar con Meta
Sincroniza las plantillas del canal indicado desde Meta: trae plantillas nuevas y actualiza estados de aprobación o recategorizaciones. Ejecute una sincronización antes de campañas importantes.
{ "ok": true, "created": 3, "updated": 5, "total": 8 }
Crear y eliminar plantillas
Crea una plantilla y la envía a aprobación de Meta (queda en pending; la aprobación toma normalmente hasta 24 horas — sincronice después para actualizar el estado), o la elimina. Meta puede recategorizar plantillas (por ejemplo, de utility a marketing); la sincronización refleja esos cambios.
Crear campaña
approved."1", "2"…) se mapea a un campo del contacto — first_name, last_name, email, phone o custom_fields.<clave>. El mensaje de cada destinatario se arma con sus propios datos.draft hasta dispararla con /send.groupIds; los duplicados se descartan automáticamente. Indique al menos uno de los dos.curl -X POST \
https://api-v2.sofiachat.com/api/campaign/{orgId} \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"name": "Promo agosto",
"integrationId": 11,
"templateId": 88,
"conversationTagId": 14,
"parameterMapping": {
"1": "first_name",
"2": "custom_fields.ciudad"
},
"groupIds": [12]
}'
{
"ok": true,
"data": {
"id": 30,
"name": "Promo agosto",
"status": "draft",
"recipientCounts": {
"total": 34, "pending": 34
}
}
}
Enviar campaña
Dispara el envío de una campaña en draft o scheduled. El procesamiento es asíncrono: la plataforma encola los mensajes y los envía de forma progresiva, con reintentos automáticos ante errores transitorios. Consulte el avance con el detalle y los destinatarios; los estados se actualizan conforme Meta confirma cada evento (enviado → entregado → leído).
curl -X POST \
https://api-v2.sofiachat.com\
/api/campaign/{orgId}/{id}/send \
-H "Authorization: Bearer {token}"
Cancelar campaña
Cancela una campaña programada o detiene el envío de los mensajes que aún estén pendientes. Los mensajes ya enviados no pueden revertirse.
Listar campañas y detalle
Listado paginado con filtro opcional por estado, y detalle individual. Cada campaña incluye sus contadores de destinatarios: total, pendientes, enviados, entregados, leídos, fallidos y omitidos.
{
"ok": true,
"data": [
{
"id": 30,
"name": "Promo agosto",
"status": "completed",
"parameter_mapping": {
"1": "first_name",
"2": "custom_fields.ciudad"
},
"recipientCounts": {
"pending": 0,
"sent": 200,
"failed": 4
}
}
],
"total": 1, "page": 1, "pageSize": 20
}
Destinatarios de una campaña
Listado paginado de destinatarios con el estado individual de cada mensaje y los datos del contacto. Filtre por status=failed después de cada campaña para depurar números inválidos de sus listas.
{
"ok": true,
"data": [
{
"id": 901,
"status": "read",
"contact": {
"id": 501,
"phone": "+50255551234",
"first_name": "Ana"
}
}
],
"total": 34, "page": 1, "pageSize": 50
}
Estados
Campaña
Destinatario
| Estado | Significado |
|---|---|
| pending | En cola, aún no enviado. |
| sent | Enviado a WhatsApp. |
| delivered | Entregado al dispositivo del destinatario. |
| read | Leído por el destinatario. |
| failed | Falló (número inválido, restricciones de Meta u otro error permanente). |
| skipped | Omitido (por ejemplo, contacto con opt-out). |
Plantilla
Ambiente y pruebas controladas
La API opera sobre un único ambiente productivo: los mensajes enviados son mensajes reales de WhatsApp. Realice sus pruebas de forma controlada:
- Grupo de prueba. Cree un grupo exclusivo con números internos de su equipo y dirija sus primeras campañas solo a él.
- Campañas en borrador. Una campaña sin
scheduledAtqueda endrafty no envía nada hasta disparar/send. Úselo para validar la creación, el mapeo de parámetros y las respuestas de la API sin generar envíos. - Plantilla de prueba. Use una plantilla genérica aprobada para validar el flujo completo (creación → envío → entrega → lectura) contra el grupo de prueba.
- Escalamiento gradual. Antes de un envío masivo, ejecute un piloto con pocos contactos reales y verifique las tasas de entrega en destinatarios.
Buenas prácticas
- Sincronice sus plantillas antes de campañas importantes, para reflejar cambios de estado o recategorizaciones hechas por Meta.
- Defina los campos personalizados primero, para que estén disponibles en la importación por Excel y en el
parameterMapping. - Límites de mensajería de Meta. El volumen diario de conversaciones iniciadas depende del nivel (tier) de su número de WhatsApp Business. Si una campaña excede el límite, los mensajes restantes quedan pendientes o fallidos.
- Respuestas de los clientes. Cuando un destinatario responde, la conversación entra al panel de Sofia Chat bajo la etiqueta configurada y puede ser atendida por el asistente de IA o por agentes humanos según su configuración.
- Auditoría de fallos. Filtre destinatarios por
status=faileddespués de cada campaña para depurar sus listas.
Soporte
Para el enrolamiento de su cuenta de WhatsApp Business, la entrega de credenciales de API o cualquier duda sobre esta integración, contacte al equipo de Sofia Chat a través de su canal de atención habitual o al correo hola@sofiachat.com.