artificialicartificialic/Docs

Primeros pasos

IntroducciónAntes de armar algo
Nuevo
Primeros pasosFacturaciónChangelog
Nuevo

Plataforma

ConversacionesContactosCanalesWeb ChatPlantillasEstadísticasEtiquetas
Nuevo
Agenda
Nuevo
OrganizaciónAjustes

Avanzado

AutomatizacionesVariables
Nuevo
Agentes IA
Nuevo
Base de ConocimientoUso de IAPlugins e IntegracionesAPI REST
Nuevo

Tutoriales

Todos los tutorialesAutomatización básicaCrear una plantilla
Nuevo
Flujo con condiciones
Nuevo
Agente IA con KB
Nuevo
Crear una difusión
Nuevo

Soporte

Preguntas frecuentesCódigos de error de Meta
Nuevo
Documentación/Avanzado/API REST

API REST

La API REST de Artificialic te permite integrar tu plataforma de mensajería con sistemas externos como CRMs, bots, ERPs o cualquier aplicación que necesite enviar mensajes o gestionar contactos programáticamente.

Esta página es para desarrolladores. Asume que sabes qué es una request HTTP, cómo enviar headers de autenticación y cómo parsear JSON. Si no eres quien va a programar la integración, pásale este link a tu equipo técnico — ellos van a saber qué hacer con esto.

Alcance actual: la API v1 cubre canales, contactos y envío de mensajes. Funcionalidades como variables de conversación, modos, automatizaciones, agentes IA y base de conocimiento se gestionan exclusivamente desde el panel — no hay endpoints REST para ellas todavía.

En esta página

  • Autenticación
  • Scopes (Permisos)
  • Formato de respuestas
  • Endpoints — Canales
  • Endpoints — Contactos
  • Endpoints — Mensajes
  • Errores comunes
  • Ejemplos de integración

Autenticación

Todas las solicitudes a la API deben incluir un header Authorization con una clave de API válida:

Authorization: Bearer ak_tu_clave_aqui

Obtener una clave de API

  1. Ve a Configuración → API en tu dashboard.
  2. Haz clic en Crear clave.
  3. Asigna un nombre descriptivo (ej. "Integración CRM") y selecciona los permisos necesarios.
  4. Copia la clave inmediatamente. Solo se muestra una vez. Si la pierdes, deberás crear una nueva.

Características de seguridad

  • Las claves tienen el prefijo ak_ seguido de 64 caracteres hexadecimales.
  • Se almacenan como un hash SHA-256 — ni siquiera nosotros podemos ver tu clave.
  • Puedes revocar una clave en cualquier momento desde el dashboard. La revocación es inmediata.
  • Cada clave registra la fecha de último uso para que puedas auditar el acceso.

Importante: Nunca expongas tu clave de API en código del lado del cliente (frontend, apps móviles). Úsala solo desde tu servidor backend.

Scopes (Permisos)

Cada clave de API tiene uno o más scopes que determinan qué operaciones puede realizar. Asigna solo los permisos que necesites (principio de menor privilegio).

ScopeDescripciónEndpoints
channels:readLeer canales conectadosGET /api/v1/channels
contacts:readListar y ver contactosGET /api/v1/contacts, GET /api/v1/contacts/:id
contacts:writeCrear, editar y eliminar contactosPOST, PATCH, DELETE /api/v1/contacts
messages:sendEnviar mensajes y plantillasPOST /api/v1/messages
messages:readConsultar el estado de entrega de un mensajeGET /api/v1/messages/:id/status

Formato de respuestas

Todas las respuestas son JSON. Las respuestas exitosas envuelven los datos en un campo data:

// Respuesta exitosa
{
  "data": {
    "id": "clxyz...",
    "name": "Juan Pérez",
    ...
  }
}

// Lista con paginación
{
  "data": [ ... ],
  "nextCursor": "clxyz..." // null si no hay más resultados
}

Las respuestas de error usan un campo error con un código máquina y un mensaje legible:

// Respuesta de error
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "API key inválida o revocada"
  }
}

Códigos HTTP

CódigoSignificado
200Operación exitosa
201Recurso creado exitosamente
400Error de validación en los datos enviados
401Clave de API faltante, inválida o revocada
403Scope insuficiente o plan sin acceso a API
404Recurso no encontrado
409Conflicto (ej. contacto duplicado)
500Error interno del servidor

Endpoints — Canales

GET
/api/v1/channels

Retorna la lista de canales conectados a tu organización. No incluye credenciales de acceso.

Scope requerido: channels:read

Query params

ParámetroTipoRequeridoDescripción
typestringNoFiltrar por tipo: WHATSAPP, MESSENGER, INSTAGRAM, WEBCHAT

Respuesta

{
  "data": [
    {
      "id": "cm1abc...",
      "name": "WhatsApp Business",
      "type": "WHATSAPP",
      "status": "CONNECTED",
      "profilePictureUrl": "https://...",
      "createdAt": "2026-01-15T10:30:00.000Z"
    }
  ]
}

Ejemplo cURL

curl -H "Authorization: Bearer ak_tu_clave" \
  https://tu-dominio.com/api/v1/channels

Endpoints — Contactos

GET
/api/v1/contacts

Lista los contactos de tu organización con paginación basada en cursor.

Scope requerido: contacts:read

Query params

ParámetroTipoRequeridoDescripción
searchstringNoBuscar por nombre, teléfono, email o ID externo (case-insensitive)
cursorstringNoID del último contacto de la página anterior (para paginación)
limitnumberNoContactos por página (default: 20, máximo: 100)

Respuesta

{
  "data": [
    {
      "id": "cm1def...",
      "name": "Juan Pérez",
      "phoneNumber": "584121234567",
      "externalId": null,
      "email": "[email protected]",
      "avatarUrl": null,
      "createdAt": "2026-02-10T08:00:00.000Z"
    }
  ],
  "nextCursor": "cm1ghi..."  // null si no hay más páginas
}

Paginación

La API usa paginación por cursor. Para obtener la siguiente página, pasa el valor de nextCursor como parámetro cursor:

# Primera página
GET /api/v1/contacts?limit=20

# Siguiente página
GET /api/v1/contacts?limit=20&cursor=cm1ghi...

Ejemplo cURL

curl -H "Authorization: Bearer ak_tu_clave" \
  "https://tu-dominio.com/api/v1/contacts?search=juan&limit=10"

GET
/api/v1/contacts/:id

Obtiene un contacto con todas sus conversaciones. Esto es clave para saber qué channelId usar al enviar un mensaje.

Scope requerido: contacts:read

Path params

ParámetroTipoRequeridoDescripción
idstringSíID del contacto

Respuesta

{
  "data": {
    "id": "cm1def...",
    "name": "Juan Pérez",
    "phoneNumber": "584121234567",
    "externalId": null,
    "email": "[email protected]",
    "avatarUrl": null,
    "metadata": null,
    "createdAt": "2026-02-10T08:00:00.000Z",
    "conversations": [
      {
        "id": "cm1conv...",
        "status": "OPEN",
        "channelId": "cm1ch...",
        "lastMessageAt": "2026-03-20T14:00:00.000Z",
        "channel": {
          "name": "WhatsApp Business",
          "type": "WHATSAPP"
        }
      }
    ]
  }
}

El array conversations te permite identificar en qué canales tiene conversaciones activas este contacto. Usa el channelId junto con el id del contacto para enviar mensajes.

Ejemplo cURL

curl -H "Authorization: Bearer ak_tu_clave" \
  https://tu-dominio.com/api/v1/contacts/cm1def...

POST
/api/v1/contacts

Crea un nuevo contacto en tu organización.

Scope requerido: contacts:write

Body (JSON)

ParámetroTipoRequeridoDescripción
namestringNoNombre del contacto
phoneNumberstringNoTeléfono en formato internacional (ej. +584121234567)
emailstringNoCorreo electrónico

Nota: Se requiere al menos name o phoneNumber. El número de teléfono se valida como formato E.164 internacional y se almacena sin el signo + (ej. 584121234567).

Respuesta (201 Created)

{
  "data": {
    "id": "cm1new...",
    "name": "María García",
    "phoneNumber": "584121234567",
    "externalId": null,
    "email": null,
    "createdAt": "2026-03-23T10:00:00.000Z"
  }
}

Errores específicos

HTTPCódigoCausa
400BAD_REQUESTFalta name y phoneNumber, o teléfono inválido
409CONFLICTYa existe un contacto con ese número de teléfono

Ejemplo cURL

curl -X POST \
  -H "Authorization: Bearer ak_tu_clave" \
  -H "Content-Type: application/json" \
  -d '{"name":"María García","phoneNumber":"+584121234567"}' \
  https://tu-dominio.com/api/v1/contacts

PATCH
/api/v1/contacts/:id

Actualiza uno o más campos de un contacto existente. Solo envía los campos que deseas modificar.

Scope requerido: contacts:write

Path params

ParámetroTipoRequeridoDescripción
idstringSíID del contacto

Body (JSON, todos opcionales)

ParámetroTipoRequeridoDescripción
namestringNoNuevo nombre
phoneNumberstringNoNuevo teléfono
emailstringNoNuevo email

Respuesta

{
  "data": {
    "id": "cm1def...",
    "name": "Juan A. Pérez",
    "phoneNumber": "584121234567",
    "externalId": null,
    "email": "[email protected]",
    "createdAt": "2026-02-10T08:00:00.000Z"
  }
}

Ejemplo cURL

curl -X PATCH \
  -H "Authorization: Bearer ak_tu_clave" \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]"}' \
  https://tu-dominio.com/api/v1/contacts/cm1def...

DELETE
/api/v1/contacts/:id

Elimina un contacto y todas sus conversaciones asociadas. Esta acción es irreversible.

Scope requerido: contacts:write

Path params

ParámetroTipoRequeridoDescripción
idstringSíID del contacto a eliminar

Respuesta

{
  "success": true
}

Ejemplo cURL

curl -X DELETE \
  -H "Authorization: Bearer ak_tu_clave" \
  https://tu-dominio.com/api/v1/contacts/cm1def...

Endpoints — Mensajes

POST
/api/v1/messages

Envía un mensaje de texto o una plantilla a un contacto. Acepta múltiples formas de identificar al contacto y al canal. Si el contacto o la conversación no existen, se crean automáticamente.

Scope requerido: messages:send

Identificación del contacto (al menos uno requerido)

ParámetroTipoRequeridoDescripción
contactIdstringNoID de un contacto existente
phoneNumberstringNoNúmero de teléfono con código de país (ej. +584121234567). Solo para canales WHATSAPP. Auto-crea contacto si no existe.
facebookIdstringNoID de Facebook/Messenger del usuario. Solo para canales MESSENGER. Auto-crea contacto si no existe.
instagramIdstringNoID de Instagram del usuario. Solo para canales INSTAGRAM. Auto-crea contacto si no existe.

Identificación del canal (al menos uno requerido)

ParámetroTipoRequeridoDescripción
channelIdstringNoID de un canal específico
channelTypestringNoTipo de canal: WHATSAPP, MESSENGER, INSTAGRAM, WEBCHAT. Usa el primer canal conectado de ese tipo.

Contenido del mensaje (exactamente uno requerido)

ParámetroTipoRequeridoDescripción
contentstringNoTexto plano del mensaje
templateobjectNoPlantilla a enviar (ver estructura abajo)
template.idstringSíID de la plantilla. Para message_template puedes usar el cuid interno (cm...) o el ID numérico que te da Meta.
template.typestringSí"message_template" (Meta/WhatsApp) o "generic_template" (plantilla genérica de la organización)
template.variablesobjectNoVariables de sustitución: {"1": "valor", "2": "valor"}

Tipos de plantilla:

  • message_template — Plantilla de WhatsApp (Meta). Debe estar aprobada. Solo funciona en canales WHATSAPP. Se envía como mensaje de plantilla nativo.
  • generic_template — Plantilla genérica de tu organización. Funciona en cualquier canal. Las variables se sustituyen y se envía como texto plano.

Flujo interno

  1. Se resuelve el canal (por ID o primer canal conectado del tipo indicado).
  2. Se resuelve o crea el contacto (por ID, teléfono, facebookId o instagramId).
  3. Se crea la conversación si no existe (upsert).
  4. Se verifica la ventana de conversación (ej. 24h para WhatsApp — las plantillas no requieren ventana abierta).
  5. Se crea el mensaje con estado PENDING.
  6. Se envía al proveedor del canal.
  7. Se actualiza el estado a SENT o DELIVERED.
  8. Se emite un evento SSE para actualización en tiempo real.

Respuesta

{
  "data": {
    "id": "cm1msg...",
    "conversationId": "cm1conv...",
    "senderType": "AGENT",
    "senderId": "cm1user...",
    "contentType": "TEXT",
    "content": "Hola, tu pedido está listo",
    "status": "SENT",
    "externalId": "wamid.abc...",
    "createdAt": "2026-03-23T10:30:00.000Z",
    "updatedAt": "2026-03-23T10:30:01.000Z",
    "sender": {
      "id": "cm1user...",
      "name": "Admin",
      "email": "[email protected]",
      "avatarUrl": null
    }
  }
}

Errores específicos

HTTPCódigoCausa
400BAD_REQUESTFalta identificador de contacto o canal
400BAD_REQUESTphoneNumber solo válido para WHATSAPP / facebookId para MESSENGER / instagramId para INSTAGRAM
400BAD_REQUESTmessage_template solo funciona en canales WHATSAPP
400BAD_REQUESTPlantilla no aprobada / Ventana de conversación expirada
404NOT_FOUNDCanal, contacto o plantilla no encontrada
400BAD_REQUESTCanal desconectado
424PROVIDER_ERROREl proveedor (Meta/WhatsApp) rechazó el envío. El campo error.message contiene la razón (token expirado, sin permisos, número inválido, etc.). El mensaje se persiste en DB con status FAILED.

Ventana de conversación: En WhatsApp, solo puedes enviar mensajes de texto libre dentro de las 24 horas posteriores al último mensaje del contacto. Después de ese período, usa una message_template aprobada para reabrir la conversación. Las plantillas genéricas (generic_template) se envían como texto y están sujetas a la misma restricción de ventana.

Ejemplo 1: Texto plano por número de teléfono

curl -X POST \
  -H "Authorization: Bearer ak_tu_clave" \
  -H "Content-Type: application/json" \
  -d '{
    "phoneNumber": "+584121234567",
    "channelType": "WHATSAPP",
    "content": "Hola, tu pedido está listo para retiro."
  }' \
  https://tu-dominio.com/api/v1/messages

Ejemplo 2: Template de WhatsApp

curl -X POST \
  -H "Authorization: Bearer ak_tu_clave" \
  -H "Content-Type: application/json" \
  -d '{
    "phoneNumber": "+584121234567",
    "channelType": "WHATSAPP",
    "template": {
      "id": "cm1tmpl...",
      "type": "message_template",
      "variables": { "1": "Juan", "2": "#12345" }
    }
  }' \
  https://tu-dominio.com/api/v1/messages

Ejemplo 3: Template genérica

curl -X POST \
  -H "Authorization: Bearer ak_tu_clave" \
  -H "Content-Type: application/json" \
  -d '{
    "contactId": "cm1def...",
    "channelId": "cm1ch...",
    "template": {
      "id": "cm1gen...",
      "type": "generic_template",
      "variables": { "1": "Juan", "2": "#12345" }
    }
  }' \
  https://tu-dominio.com/api/v1/messages

Ejemplo 4: Retrocompatible (contactId + channelId + content)

curl -X POST \
  -H "Authorization: Bearer ak_tu_clave" \
  -H "Content-Type: application/json" \
  -d '{
    "contactId": "cm1def...",
    "channelId": "cm1ch...",
    "content": "Hola, tu pedido está listo."
  }' \
  https://tu-dominio.com/api/v1/messages

GET
/api/v1/messages/:id/status

Consulta el estado de entrega actual de un mensaje. La respuesta inicial del POST /api/v1/messages indica solo que el mensaje fue encolado en el proveedor (status SENT); los estados posteriores (DELIVERED, READ, FAILED) llegan de manera asíncrona a través de webhooks. Este endpoint te permite consultar el estado más reciente sin tener que escuchar webhooks.

Scope requerido: messages:read

Parámetros de URL

ParámetroTipoRequeridoDescripción
idstringSíID del mensaje. Acepta el cuid interno (cm...) o el externalId del proveedor (en WhatsApp es el wamid devuelto al enviar).

Respuesta

{
  "data": {
    "id": "cm1msg...",
    "externalId": "wamid.HBg...",
    "status": "DELIVERED",
    "errorMessage": null,
    "contentType": "TEMPLATE",
    "conversationId": "cm1conv...",
    "createdAt": "2026-03-23T10:30:00.000Z",
    "updatedAt": "2026-03-23T10:30:05.123Z"
  }
}

Estados posibles

StatusSignificado
PENDINGEl mensaje se creó pero aún no se envió al proveedor.
SENTEl proveedor (Meta, etc.) aceptó el mensaje y lo encoló para entrega.
DELIVEREDEl mensaje llegó al dispositivo del destinatario.
READEl destinatario abrió el chat y vio el mensaje (si tiene acuses de lectura activados).
FAILEDEl proveedor rechazó la entrega. El campo errorMessage contiene la razón.

Errores específicos

HTTPCódigoCausa
403FORBIDDENLa API key no tiene scope messages:read
404NOT_FOUNDEl mensaje no existe o pertenece a otra organización

Ejemplo: consultar por wamid

curl -H "Authorization: Bearer ak_tu_clave" \
  https://tu-dominio.com/api/v1/messages/wamid.HBgMNTg.../status

Ejemplo: consultar por cuid interno

curl -H "Authorization: Bearer ak_tu_clave" \
  https://tu-dominio.com/api/v1/messages/cm1msg.../status

Errores comunes

HTTPCódigoCausa probableSolución
401UNAUTHORIZEDFalta el header AuthorizationAgrega Authorization: Bearer ak_...
401UNAUTHORIZEDClave inválida o revocadaVerifica la clave en Configuración → API
403FORBIDDENScope insuficienteCrea una clave nueva con el scope necesario
403FORBIDDENPlan sin acceso a APIActualiza tu plan a uno que incluya API dedicada
404NOT_FOUNDRecurso no encontrado o no pertenece a tu orgVerifica el ID del recurso
409CONFLICTDuplicado (ej. mismo teléfono)Busca el contacto existente antes de crear

Ejemplos de integración

Flujo completo: enviar un mensaje a un contacto

Este ejemplo muestra cómo obtener los canales, buscar un contacto y enviarle un mensaje usando JavaScript (Node.js / fetch):

const API_URL = "https://tu-dominio.com";
const API_KEY = "ak_tu_clave_aqui";

const headers = {
  "Authorization": `Bearer ${API_KEY}`,
  "Content-Type": "application/json",
};

// 1. Obtener canales disponibles
const channelsRes = await fetch(`${API_URL}/api/v1/channels`, { headers });
const { data: channels } = await channelsRes.json();
const whatsappChannel = channels.find(ch => ch.type === "WHATSAPP");

console.log("Canal WhatsApp:", whatsappChannel.id);

// 2. Buscar contacto por teléfono
const contactsRes = await fetch(
  `${API_URL}/api/v1/contacts?search=584121234567`,
  { headers }
);
const { data: contacts } = await contactsRes.json();
const contact = contacts[0];

console.log("Contacto:", contact.id, contact.name);

// 3. Enviar mensaje
const msgRes = await fetch(`${API_URL}/api/v1/messages`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    contactId: contact.id,
    channelId: whatsappChannel.id,
    content: "Hola, tu pedido #1234 está listo para retiro.",
  }),
});

const { data: message } = await msgRes.json();
console.log("Mensaje enviado:", message.id, "Estado:", message.status);

Mismo flujo con cURL

# 1. Listar canales
curl -s -H "Authorization: Bearer ak_tu_clave" \
  https://tu-dominio.com/api/v1/channels

# 2. Buscar contacto
curl -s -H "Authorization: Bearer ak_tu_clave" \
  "https://tu-dominio.com/api/v1/contacts?search=584121234567"

# 3. Enviar mensaje
curl -X POST \
  -H "Authorization: Bearer ak_tu_clave" \
  -H "Content-Type: application/json" \
  -d '{
    "contactId": "CONTACT_ID",
    "channelId": "CHANNEL_ID",
    "content": "Hola, tu pedido #1234 está listo para retiro."
  }' \
  https://tu-dominio.com/api/v1/messages

Consejo: Guarda los IDs de canales y contactos frecuentes en tu base de datos para no tener que consultarlos en cada envío.

AvanzadoPlugins e IntegracionesTutorialesTodos los tutoriales
© 2026 Artificialic, Inc.
Estado de serviciosTérminosPrivacidad