API, webhooks e integraciones
Alcance y versiones
tuagenteia24.com publica tres contratos independientes:
| Contrato | Base | Autenticación | Uso |
|---|---|---|---|
| API empresarial v1 | /api/v1 |
Bearer c369_... |
Integraciones de una empresa y aplicaciones propias |
| API móvil v1 | /api/mobile/v1 |
Laravel Sanctum | Aplicación de agentes de atención |
| API pública | /api/public |
Clave pública y sesión firmada | Widget web y chat público |
Las rutas /api/v1 están aisladas a la empresa del token. La administración global de la plataforma no se expone a tokens empresariales. Los cambios incompatibles se publicarán bajo otra versión.
Autenticación
Las claves se crean en /developers, comienzan con c369_, se muestran una sola vez y se almacenan mediante SHA-256. Cada clave conserva empresa, usuario creador, capacidades, vencimiento, revocación y último uso. Si el creador deja de ser miembro activo, la clave deja de funcionar.
Authorization: Bearer c369_REEMPLAZAR
Accept: application/json
Content-Type: application/json
No coloque claves en JavaScript público, URLs, repositorios, aplicaciones móviles ni workflows exportados.
Capacidades
| Dominio | Lectura | Escritura |
|---|---|---|
| Asistentes | assistants.read |
assistants.write |
| Conversaciones | conversations.read, messages.read |
conversations.write, messages.write |
| Leads y contactos | leads.read, contacts.read |
leads.write, contacts.write |
| Productos y reservas | products.read, bookings.read |
products.write, bookings.write |
| CRM y cotizaciones | crm.read, quotes.read |
crm.write, quotes.write |
Una ruta responde 403 e indica required cuando falta una capacidad. Evite la capacidad global * en producción.
Convenciones
- Fechas: ISO 8601 con zona horaria.
- Monedas: código ISO 4217 de tres letras.
- Importes terminados en
_cents: centavos enteros. - Listas:
pageyper_page; el máximo es 100. - Escrituras: JSON UTF-8, salvo archivos.
- Idempotencia: respuestas de conversación aceptan un UUID en
idempotency_key.
Las listas incluyen data, current_page, per_page, last_page, total, from, to, URLs y enlaces de paginación.
Endpoints API v1
Base de producción: https://tuagenteia24.com/api/v1.
Ejemplo completo de API: /api/v1/conversations.
Asistentes
GET /assistants
POST /assistants
GET /assistants/{assistant}
PUT /assistants/{assistant}
PUT /assistants/{assistant}/status
DELETE /assistants/{assistant}
Alta mínima: {"name":"Ventas","language":"es","tone":"professional","starting_experience":"ai"}. Los estados son draft, processing, active, paused, suspended y archived. El borrado es lógico.
Conversaciones y mensajes
GET /conversations?status=active&assistant_id=1&per_page=25&page=1
POST /conversations
GET /conversations/{conversation}
POST /conversations/{conversation}/messages
PUT /conversations/{conversation}/claim
PUT /conversations/{conversation}/assign
PUT /conversations/{conversation}/return-to-ai
PUT /conversations/{conversation}/close
PUT /conversations/{conversation}/workflow
PUT /conversations/{conversation}/priority
POST /conversations/{conversation}/notes
Inicio externo:
{"assistant_id":12,"external_user_id":"crm-804","event_id":"evt-0001","message":"Necesito información","name":"María Cliente","email":"maria@example.com"}
Respuesta: {"message":"Estamos revisando tu solicitud.","idempotency_key":"7b594eed-b7f8-42c2-a9ef-690eb6216bf3"}.
Asignar requiere user_id. Cerrar acepta close_reason: resolved, abandoned, spam, other. El workflow admite open, pending, waiting_customer, resolved; prioridad admite low, normal, high, urgent.
Leads
GET /leads
POST /leads
GET /leads/{lead}
PUT /leads/{lead}
DELETE /leads/{lead}
La escritura admite assistant_id, conversation_id, contact_id, datos personales, interest, status, source, metadata y consent_at.
Contactos
GET /contacts?status=active
GET /contacts/{contact_public_id}
POST /contacts
PUT /contacts/{contact_public_id}
POST /contacts/{contact_public_id}/identities
DELETE /contacts/{contact_public_id}/identities/{identity}
POST /contacts/{contact_public_id}/notes
POST /contacts/{contact_public_id}/consents
POST /contacts/{contact_public_id}/merge
DELETE /contacts/{contact_public_id}/personal-data
{"name":"María Cliente","company":"Empresa Demo","identities":[{"type":"email","value":"maria@example.com"},{"type":"phone","value":"+51999888777","verified":true}],"custom_fields":{"crm_id":"C-1024"}}
Las identidades se normalizan, cifran y deduplican. type admite email, phone, external_id; el estado admite active y blocked.
La fusión recibe target_contact_id interno y traslada identidades, conversaciones, leads, notas, consentimientos, reservas y CRM. La anonimización es irreversible y elimina datos personales, por lo que debe concederse contacts.write solamente a integraciones confiables.
Productos
GET /products?assistant_id=12
POST /products
GET /products/{product}
PUT /products/{product}
DELETE /products/{product}
El alta requiere assistant_id, sku, name, price, currency y stock. Admite descripción, categoría, marca, oferta, atributos, imagen, URL, estado y variaciones. El catálogo se reindexa después de escribir.
Reservas
GET /booking-services
POST /booking-services
PUT /booking-services/{service}
DELETE /booking-services/{service}
GET /booking-resources
POST /booking-resources
PUT /booking-resources/{resource}
DELETE /booking-resources/{resource}
GET /booking-availability?service_id=1&resource_id=2&date=2026-08-24
GET /bookings?status=confirmed&from=2026-08-22
POST /bookings
POST /bookings/{booking_public_id}/cancel
PUT /bookings/{booking_public_id}/reschedule
{"service_id":1,"resource_id":2,"starts_at":"2026-08-24T10:00:00-05:00","customer_name":"María Cliente","customer_email":"maria@example.com","attendee_count":1}
La disponibilidad valida plan, horarios, excepciones, capacidad, anticipación y calendario externo. Un servicio o recurso con citas debe desactivarse en vez de eliminarse.
CRM
GET /crm/pipelines
POST /crm/pipelines
GET /crm/pipelines/{pipeline}
PUT /crm/pipelines/{pipeline}
DELETE /crm/pipelines/{pipeline}
PUT /crm/pipelines/{pipeline}/stages
GET /crm/opportunities
POST /crm/opportunities
GET /crm/opportunities/{opportunity}
PUT /crm/opportunities/{opportunity}
DELETE /crm/opportunities/{opportunity}
PUT /crm/opportunities/{opportunity}/stage
GET /crm/activities
POST /crm/activities
PUT /crm/activities/{activity}
PUT /crm/activities/{activity}/complete
DELETE /crm/activities/{activity}
Las etapas usan outcome: open, won o lost. Crear una oportunidad requiere contact_id, crm_stage_id, title, amount_cents, currency y probability. Mover a una etapa perdida exige loss_reason. Cada movimiento conserva el historial y tiempo en etapa.
Las actividades admiten task, call, meeting, email y note; se pueden filtrar por contacto, oportunidad, responsable y estado.
Cotizaciones
GET /quotes
POST /quotes
GET /quotes/{quote_public_id}
PUT /quotes/{quote_public_id}
DELETE /quotes/{quote_public_id}
POST /quotes/{quote_public_id}/send
POST /quotes/{quote_public_id}/revise
GET /quotes/{quote_public_id}/pdf
{
"contact_id": 10,
"crm_opportunity_id": 20,
"title": "Propuesta anual",
"currency": "USD",
"issued_at": "2026-08-22",
"valid_until": "2026-09-05",
"items": [{"name":"Implementación","quantity":2,"unit_price":100,"discount_percent":10}],
"discounts": [{"name":"Promoción","type":"percentage","value":10}],
"taxes": [{"name":"IGV","rate":18}]
}
El servidor calcula subtotales, descuentos, impuestos y total; nunca confía en totales enviados por el cliente. Cada actualización de borrador crea una revisión inmutable. Enviar genera PDF, acceso firmado y correo; después del envío se debe abrir una revisión antes de editar.
API móvil del agente
Base: https://tuagenteia24.com/api/mobile/v1. El login devuelve un token o solicita 2FA. Guarde el token Sanctum en el almacenamiento seguro del dispositivo.
POST /auth/login
POST /auth/two-factor
DELETE /auth/logout
GET /me
POST /devices
DELETE /devices
GET /conversations
GET /conversations/{conversation}
POST /conversations/{conversation}/messages
PUT /conversations/{conversation}/claim
PUT /conversations/{conversation}/close
POST /devices registra FCM; DELETE /devices lo revoca. Tras el login se requiere Bearer Sanctum y una empresa activa.
API pública del widget
Estas rutas no aceptan tokens empresariales. La configuración y el inicio usan la clave pública; las demás requieren la sesión firmada del visitante.
GET /api/public/assistants/{publicKey}/config
POST /api/public/assistants/{publicKey}/conversations
POST /api/public/assistants/{publicKey}/messages
GET /api/public/conversations/{publicId}/messages
POST /api/public/conversations/{publicId}/lead
POST /api/public/conversations/{publicId}/typing
POST /api/public/conversations/{publicId}/presence
POST /api/public/conversations/{publicId}/request-human
POST /api/public/conversations/{publicId}/messages/{message}/feedback
POST /api/public/conversations/{publicId}/attachments
POST /api/public/conversations/{publicId}/rating
GET /api/public/conversations/{publicId}/transcript
POST /api/public/conversations/{publicId}/broadcasting/auth
No reutilice una sesión entre visitantes. Los límites de frecuencia son específicos por operación.
Errores
| HTTP | Significado |
|---|---|
401 |
Token ausente, inválido, expirado o revocado |
403 |
Capacidad insuficiente, empresa suspendida o creador inactivo |
404 |
Recurso inexistente o de otra empresa |
409 |
Conflicto con el estado actual |
422 |
Validación o regla de negocio |
429 |
Límite excedido |
500 |
Error interno |
La validación usa {"message":"...","errors":{"campo":["..."]}}. Reintente con espera exponencial solo 429 y 5xx.
Webhooks salientes
Eventos: message.created, conversation.handoff_requested, conversation.assigned, conversation.closed, lead.created, contact.created, contact.updated, contact.merged, contact.consent.updated, booking.created, booking.cancelled, booking.rescheduled, booking.completed, booking.no_show.
El payload contiene id, event, created_at y data. Los encabezados son X-Chat369-Event, X-Chat369-Event-Id, X-Chat369-Timestamp y X-Chat369-Signature; se conservan por compatibilidad.
La firma es v1= + HMAC-SHA256(secreto, timestamp + "." + cuerpo_json_exacto). Valide un máximo de cinco minutos, use los bytes originales y compare en tiempo constante.
$body = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_CHAT369_TIMESTAMP'] ?? '';
$received = $_SERVER['HTTP_X_CHAT369_SIGNATURE'] ?? '';
$expected = 'v1='.hash_hmac('sha256', $timestamp.'.'.$body, getenv('TUAGENTE_WEBHOOK_SECRET'));
if (abs(time() - (int) $timestamp) > 300 || ! hash_equals($expected, $received)) {
http_response_code(401); exit;
}
http_response_code(204);
Se acepta cualquier 2xx. La cola integrations realiza hasta cinco intentos progresivos, limita la respuesta, exige HTTPS y bloquea destinos privados por defecto.
Webhooks entrantes
GET /api/webhooks/whatsapp
POST /api/webhooks/whatsapp
GET /api/webhooks/channels/{connection}/{secret}
POST /api/webhooks/channels/{connection}/{secret}
POST /api/webhooks/marketplace/{connection}/{secret}
POST /api/webhooks/izipay
POST /api/webhooks/booking-payments/izipay
Cada proveedor usa su propio secreto o firma. No llame estas rutas desde la app móvil.
n8n y otras herramientas
En n8n use el Webhook node para eventos entrantes y HTTP Request para llamar la API.
- Cree una clave con capacidades mínimas.
- Guárdela como credencial Bearer, nunca como texto del workflow.
- Cree un endpoint HTTPS y seleccione eventos en
/developers. - Verifique firma e idempotencia antes de procesar.
- Responda rápidamente
2xxy delegue el trabajo lento. - Para mensajes genere un UUID estable por ejecución.
Operación y seguridad
- Mantenga Horizon consumiendo
integrationsy las colas de mensajes, reservas y notificaciones. - Mantenga
INTEGRATION_ALLOW_PRIVATE_WEBHOOK_URLS=false. - Rote claves al cambiar responsables o ante exposición.
- Supervise
401,403,422,429, entregas fallidas yfailed_jobs. - No registre tokens, secretos, credenciales de canales ni datos sensibles completos.
- Los receptores deben tolerar duplicados, eventos fuera de orden y reintentos.
- Pruebe escrituras masivas primero en una empresa y asistente de prueba.