Guarda un mensaje en una conversación: crea la conversación si no se envía questionId, o agrega el mensaje al historial si questionId ya existe. Pensado para integraciones que orquestan la IA por su cuenta y solo necesitan persistir los mensajes en el Inbox/CRM de Mapaprop (a diferencia de POST /chat, que además genera la respuesta).
Este endpoint siempre descuenta el tokensUsed que le envíes del saldo de tokens de IA de la cuenta (customer_ai_usage), incluso si vos generaste la respuesta con tu propio motor. Si tu integración no consume tokens de Mapaprop, enviá tokensUsed: 0. Para guardar pasos del flujo guiado (por ejemplo, un click en un botón) sin tocar el contador de tokens, usá POST /thread en su lugar.
| Información del recurso | |
|---|---|
| Autenticación | Requerida (Token de API, Bearer) |
| Scope | mapaprop-chat-ai |
| HTTP Method | POST |
| Response | JSON |
| Version | 1 |
URL del recurso
https://mapaprop.app/api/action/mapaprop-chat-ai-v1/message
Parámetros
customerId y websiteId se derivan del token de autenticación, no se envían en el body.
| Key | Type | Required | Descripción |
|---|---|---|---|
| message | string | sí | El contenido del mensaje. |
| direction | int | sí | 1 = mensaje del visitante, 3 = mensaje de la IA. La resolución del remitente (from) solo distingue estos dos casos: si necesitás registrar un mensaje de un asesor humano o del sistema (direction=2), usá POST /thread en su lugar. |
| questionId | int | no | ID de la conversación a la que agregar el mensaje. Si se omite, se crea una conversación nueva. |
| leadName | string | no | Nombre del visitante. Default Visitante. |
| leadEmail | string | no | Email del visitante. Si se envía y la conversación todavía no tiene contacto asociado, se crea o vincula un contacto en el CRM. |
| leadPhone | string | no | Teléfono del visitante. |
| sourceUrl | string | no | URL de la página donde el visitante envió el mensaje. Solo se usa al crear una conversación nueva (cuando no se envía questionId). |
| sessionId | string | no | Identificador de sesión. Si no se envía, se genera un UUID automáticamente. |
| tokensUsed | int | no | Cantidad de tokens de IA a descontar del saldo del cliente por este mensaje. Default 0. |
| propertiesReferenced | array de int | no | IDs de propiedades referenciadas en el mensaje. Se guarda como metadata de la conversación. |
| customerSearch | object | no | Datos de búsquedas/favoritos/consultas del visitante, usados para enriquecer el contacto en el CRM. |
Código de ejemplo
POST /api/action/mapaprop-chat-ai-v1/message HTTP/1.1
Host: mapaprop.app
Content-Type: application/json
Authorization: Bearer {access_token}
{
"questionId": 481203,
"message": "Sí, tenemos 3 departamentos de 2 ambientes en Palermo.",
"direction": 3,
"tokensUsed": 0
}
Respuesta
| Objeto | Campo | Tipo | Requerido | Descripción |
|---|---|---|---|---|
| Response | success | boolean | sí | true cuando el mensaje se guardó correctamente. |
| questionId | int | sí | El ID de la conversación (el mismo que enviaste, o el recién creado). | |
| tokensUsed | int | sí | El tokensUsed que enviaste en la request. | |
| totalTokensUsed | int | sí | Total de tokens consumidos por el cliente en el período de facturación actual, luego de este mensaje. | |
| tokensRemaining | int | sí | Tokens de IA restantes en el período actual. |
En caso de error, no llega el shape de arriba con success: false: la request se corta con un error (ver tabla siguiente).
Errores
| Error | Causa |
|---|---|
QUESTION_NOT_FOUND | El questionId enviado no existe o no pertenece a este cliente. |
SYSTEM_ERROR | Falló el guardado del mensaje por otro motivo (por ejemplo, error de base de datos). |
Errores de validación (se corta la request, no llega success: false)
| Error | Causa |
|---|---|
REQUIRED_INPUT — "Message is required" | Falta el campo message. |
REQUIRED_INPUT — "Direction is required (1=visitor, 3=AI)" | Falta el campo direction. |
Ejemplo de respuesta
{
"success": true,
"questionId": 481203,
"tokensUsed": 0,
"totalTokensUsed": 12450,
"tokensRemaining": 87550
}
Ejemplo de error:
{
"success": false,
"error": "QUESTION_NOT_FOUND"
}