Una integración entre servidores
Tu servidor crea conversaciones y envía mensajes a la bandeja externa de Aztraliz. Las respuestas del equipo regresan a tu servidor mediante webhooks firmados. Las notas internas, auditoría y datos de credenciales no forman parte de la API pública.
El contrato publicado es 1.1 y conserva las rutas compatibles /api/messaging/v1. La respuesta HTTP incluye X-Aztraliz-API-Version: 1.1. Configura el host proporcionado por el administrador del negocio; la API no se sirve desde esta landing.
https://<host-de-aztraliz>/api/messaging/v1La credencial identifica al negocio y a la integración. Tu servidor debe autenticar a cada usuario de tu app y verificar que pueda acceder a la conversación solicitada. Los endpoints no aceptan tenantId, tenant ni populate.
Credenciales y permisos
Un administrador abre Configuración → Integraciones → Mensajería → Apps externas. Registra el nombre, un appKey estable y único en el negocio, la URL HTTPS de tu webhook en el puerto 443 y los permisos necesarios. El identificador empieza con una letra minúscula, admite letras minúsculas, números, guiones y guiones bajos y tiene de 2 a 64 caracteres.
El token de acceso y el secreto del webhook se muestran una sola vez. Consérvalos en el gestor de secretos de tu servidor. No los incluyas en código público, apps móviles, URLs ni registros.
Authorization: Bearer <token-de-messaging>
Content-Type: application/json| Permiso | Permite |
|---|---|
| conversations:read | Listar y consultar conversaciones. |
| conversations:write | Crear o recuperar conversaciones. |
| messages:read | Leer el historial y recuperar respuestas. |
| messages:write | Enviar mensajes y subir archivos si están habilitados. |
| receipts:write | Confirmar entrega y lectura de respuestas. |
GET /me valida una credencial activa, informa sus permisos y devuelve capabilities.media. El icono de la aplicación es opcional y se administra desde Ajustes; no lo sube el cliente mediante esta API.
Inicio rápido
Descarga el cliente de referencia para Node.js. Configura AZTRALIZ_BASE_URL con el origen HTTPS de tu entorno y AZTRALIZ_MESSAGING_TOKEN con su token.
import { createMessagingClient } from "./client.mjs";
// Ejecuta este código en tu servidor (Node.js 20+).
const messaging = createMessagingClient({
baseUrl: process.env.AZTRALIZ_BASE_URL,
token: process.env.AZTRALIZ_MESSAGING_TOKEN,
});
await messaging.me();
const { data: conversation } = await messaging.upsertConversation({
externalId: "support-order-482",
contact: { externalId: "user-91", name: "Ana" },
context: { orderId: "482" },
});
await messaging.sendMessage(conversation.id, {
externalId: "client-message-00042",
text: "¿Cuándo llega mi pedido?",
});Los identificadores del ejemplo son ilustrativos. Genéralos y guárdalos antes del primer intento. El cliente de referencia no reintenta automáticamente.
curl "$AZTRALIZ_BASE_URL/api/messaging/v1/me" \
-H "Authorization: Bearer $AZTRALIZ_MESSAGING_TOKEN"Endpoints del contrato
Todas las rutas son relativas a la URL base de tu entorno. El archivo OpenAPI incluye los esquemas completos, campos, respuestas y códigos de error.
Desliza la tabla horizontalmente para ver todas las columnas.
| Método | Ruta | Operación |
|---|---|---|
| GET | /me | Verify integration and scopes |
| GET | /conversations | List owned conversations |
| POST | /conversations | Create or recover a conversation |
| GET | /conversations/{conversationId} | Read a conversation |
| GET | /conversations/{conversationId}/messages | Read chronological history |
| POST | /conversations/{conversationId}/messages | Send a customer message to Aztraliz |
| POST | /conversations/{conversationId}/messages/{messageId}/receipt | Confirm delivery or reading |
| POST | /conversations/{conversationId}/attachments | Upload one managed file (messages:write) |
Mensajes e idempotencia
POST /conversations crea o recupera una conversación por negocio, integración y externalId. Devuelve 201 al crear y 200 al recuperar; conserva el data.id devuelto. Repetir la identidad con otro contacto produce 409 CONTACT_CONFLICT.
Envía el teléfono internacional opcional en contact.phone para vincular al cliente cuando exista una coincidencia única dentro del negocio. Un teléfono ambiguo requiere vinculación manual.
{
"externalId": "client-message-00042",
"text": "¿Cuándo llega mi pedido?"
}POST /conversations/{conversationId}/messages acepta texto de hasta 4,000 bytes UTF-8 y replyTo opcional con el ID de un mensaje de la misma conversación. El externalId debe identificar al mensaje antes del primer envío.
Repite exactamente los mismos IDs y contenido si pierdes la respuesta. Un mensaje ya persistido se devuelve con 200; cambiar el contenido con el mismo ID produce 409 IDEMPOTENCY_CONFLICT. Dos mensajes distintos necesitan IDs diferentes, aunque el texto coincida.
Imágenes, audio, video y documentos
El administrador debe activar archivos en la integración. Comprueba capabilities.media === true en GET /me; requiere messages:write. Las integraciones conservan solo texto por defecto.
- Sube cada archivo con
multipart/form-dataa/conversations/{conversationId}/attachments. Envía únicamenteexternalIdyfile; deja que el cliente HTTP genere el boundary. - Guarda el ID de cada archivo y su orden. La subida por sí sola no crea un mensaje.
- Publica un mensaje con
attachmentscomo arreglo de esos IDs. Puedes incluir texto y una cita.
{
"externalId": "order-482-message-1",
"text": "Este es el comprobante.",
"attachments": [
"<id-del-archivo>"
]
}Límites: 25 MiB por archivo, 8 archivos y 100 MiB por mensaje. Una subida sin usar vence a las 24 horas; hay un máximo de 100 subidas pendientes por integración. No envíes URLs externas ni base64 como adjuntos.
Se admiten imágenes JPEG, PNG, GIF, WebP, HEIC y HEIF; video MP4, QuickTime y WebM; audio MPEG, MP4, AAC, OGG, WAV y WebM; PDF, TXT, CSV, documentos de Office y ZIP. Consulta los MIME exactos en OpenAPI. Las URLs de archivos son compartibles: no equivalen a una sesión privada de tu usuario.
Recibir respuestas y eventos firmados
Tu webhook recibe message.created cuando un asesor responde y conversation.deleted tras una eliminación administrativa. El webhook de mensajes usa apiVersion: "1.0" en integraciones de solo texto y "1.1" cuando admiten archivos. El evento de eliminación siempre usa "1.1".
X-Aztraliz-Event-Id: <id-del-evento>
X-Aztraliz-Timestamp: <segundos-unix>
X-Aztraliz-Signature: v1=<hex-hmac-sha256>Verifica HMAC-SHA256 sobre timestamp + "." + cuerpo HTTP original, usando el secreto del webhook y comparación de tiempo constante, antes de parsear el JSON. Rechaza timestamps con más de cinco minutos de diferencia y comprueba que el ID del header coincida con el del evento.
- Deduplica por integración e ID del evento en almacenamiento persistente.
- Guarda el mensaje y sus adjuntos dentro de la misma transacción.
- Confirma la transacción y responde
204o cualquier2xx. Ante fallas de persistencia responde5xx.
La entrega es al menos una vez: puede haber duplicados y eventos fuera de orden. El timeout por intento es de 10 segundos, con hasta 12 intentos y espera exponencial de 30 segundos a una hora. El administrador puede reintentar entregas que requieren atención. El cuerpo de eventos admite hasta 64 KiB.
Para conversation.deleted, serializa el procesamiento con los mensajes del mismo ID de conversación, conserva una marca persistente de eliminación y elimina la copia local de ese chat. Esa marca evita que un mensaje atrasado restaure el historial. Borra por el ID de Aztraliz, nunca solo por externalId: el mismo identificador externo puede reutilizarse en un chat nuevo. Guarda la marca fuera de las tablas eliminadas en cascada y notifica a los clientes de tu app tras el commit.
El receptor de referencia valida firma, ventana temporal y tamaño. Debes aportar el adaptador de persistencia, deduplicación y distribución a tus clientes.
Confirmar entrega y lectura
POST /conversations/{conversationId}/messages/{messageId}/receipt
{ "status": "read" }Usa delivered cuando el dispositivo haya recibido una respuesta y read cuando la persona la haya leído. Las confirmaciones son idempotentes y no retroceden de lectura a entrega. Solo aplican a mensajes salientes.
queued: respuesta guardada y pendiente de entrega a tu servidor.sent: tu servidor respondió2xxal webhook.delivered: tu app confirmó entrega; en mensajes entrantes, Aztraliz confirmó persistencia.read: tu app confirmó lectura.failed: se agotaron los intentos o se revocó la integración antes de la entrega.
Historial y paginación
Lista conversaciones con GET /conversations y recupera mensajes con GET /conversations/{conversationId}/messages. Usa limit de 1 a 100, por defecto 50, y after con el cursor recibido.
meta.hasMore y meta.nextCursor recorren las páginas; meta.lastCursor permite continuar luego del último registro. Los mensajes se devuelven del más antiguo al más reciente. Los cursores son opacos y pertenecen a una integración y colección.
Un mensaje obtenido por historial y luego por webhook debe actualizar el mismo registro. Los cambios de estado no reaparecen al avanzar el cursor; conserva la respuesta del recibo y vuelve a consultar cuando necesites reconciliar.
Errores y límites de uso
{
"ok": false,
"error": {
"code": "SCOPE_FORBIDDEN",
"message": "Missing required permission"
},
"requestId": "<id-para-diagnostico>"
}Usa el estado HTTP y error.code, no el texto del mensaje, para decidir qué hacer. Conserva requestId para diagnóstico.
| HTTP | Acción |
|---|---|
| 400 | Corrige JSON, campos o cursor. |
| 401 / 403 | Revisa token, estado de la integración y permisos. |
| 404 | Comprueba que los IDs pertenezcan a esta integración. |
| 409 | Resuelve el conflicto de identidad, contenido o capacidad de media. |
| 410 | Una subida venció; revisa primero si el mensaje original ya se publicó. |
| 413 / 415 | Reduce el tamaño o corrige formato y MIME. |
| 429 | Respeta Retry-After y reduce solicitudes. |
| 503 | Reintenta con espera y los mismos identificadores. |
Hay 120 operaciones públicas exitosas por minuto por integración y un límite de entrada de 600 solicitudes por minuto por IP. Una subida de archivos consume dos operaciones: autorización y persistencia. El JSON admite hasta 32 KiB. Evita el polling continuo y respeta el header Retry-After.
Rotación y ciclo de vida
La rotación del token invalida el anterior de inmediato. Al rotar el secreto del webhook, el siguiente intento usa el nuevo secreto; coordina el cambio con tu receptor.
Pausar bloquea nuevas llamadas y respuestas, conservando entregas pendientes. Revocar es permanente y conserva el historial. La eliminación de conversaciones corresponde al administrador de Aztraliz y no se expone como operación pública de terceros.
El contrato actual incluye texto, archivos administrados, citas, historial, recibos y eventos de eliminación. No incluye typing externo, reacciones, edición o eliminación individual de mensajes ni OAuth para instalar apps de marketplace.
Contrato y ejemplos descargables
Importa OpenAPI en Postman, Insomnia o tu generador de clientes. Configura siempre el host y las credenciales del mismo entorno. Antes de habilitar usuarios, verifica envío, respuestas firmadas, deduplicación, recuperación de historial y aislamiento de conversaciones entre usuarios de tu aplicación.
Conocer Aztraliz Pulse