Ir al contenido

Resumen de la API

Todos los endpoints REST de RolChat siguen un mismo contrato: la misma URL base, el mismo sobre de respuesta, la misma paginación, la misma forma de error. Apréndelo una vez y todas las familias de endpoints de la referencia de endpoints se leerán igual.

https://api.rolchat.com/api/v1/

La versión está en la ruta. Añadir campos opcionales, endpoints nuevos o parámetros de consulta nuevos con valores predeterminados no es un cambio incompatible y no incrementa la versión. Los cambios incompatibles se publican como v2, y los endpoints de v1 declarados obsoletos siguen funcionando al menos seis meses después de su anuncio (consulta Obsolescencia).

Método Cabecera Se usa para
JWT bearer Authorization: Bearer <access_token> Sesiones interactivas (la aplicación web, las apps móviles)
Clave de API Authorization: Bearer rcp_<secret> Llamadas entre máquinas, claves de API de plugins
Firma HMAC X-RolChat-Signature: sha256=… Webhooks entrantes desde tus sistemas, consulta Webhooks
Ninguno - Endpoints públicos del widget (/widget/…, /forms/…), limitados por sitio y origen

Para las integraciones usa una clave de API (un token de acceso personal). Las claves se crean en Configuración → Plugins → Claves de API de RolChat, se muestran una sola vez y se almacenan solo como hash. Una clave nunca puede hacer más que el miembro que la creó: en cada llamada sus ámbitos se comprueban frente a los permisos actuales de ese miembro. Consulta Autenticación para la duración de los JWT, la cabecera X-Account-Id y las sesiones con varias empresas.

Un recurso individual:

{
"data": { "id": "cnt_01HK…", "email": "ada@example.com" },
"meta": {
"request_id": "req_01HK…"
}
}

Una lista:

{
"data": [ { … }, { … } ],
"meta": {
"request_id": "req_01HK…",
"count": 50,
"next_cursor": "cur_01HK…",
"prev_cursor": "cur_01HK…",
"has_more": true
}
}

Las respuestas sin cuerpo (204 No Content tras una eliminación) siguen incluyendo la cabecera X-Request-Id.

Un error:

{
"errors": [
{
"code": "validation_failed",
"message": "Email must be valid.",
"field": "email",
"details": { "received": "not-an-email" }
}
],
"meta": { "request_id": "req_01HK…" }
}

code es legible por máquina, en snake_case, y es el valor sobre el que conviene ramificar; message está en inglés y está pensado para los registros. field y details aparecen cuando ayudan y nunca contienen datos personales. La API nunca responde 200 con un array errors: si hay errores, el estado es 400 o superior. La lista completa de códigos está en la página Errores.

Los endpoints de lista que pueden crecer usan paginación por cursor. Pide la primera página sin cursor y después devuelve tal cual el next_cursor que recibiste:

GET /api/v1/contacts?limit=50
GET /api/v1/contacts?limit=50&cursor=eyJrIjoi…
  • limit vale 50 por defecto y tiene un máximo de 200; los valores mayores se rechazan con 400 validation_failed.
  • Los cursores son opacos y caducan a las 24 horas (400 validation_failed con code: cursor_expired).
  • Los resultados son coherentes con la instantánea tomada en la primera página: los registros eliminados entre páginas desaparecen y los nuevos solo aparecen cuando empiezas de nuevo sin cursor.
  • También se envía una cabecera Link con rel="next" y rel="prev" para los clientes que la prefieran.

Envía una cabecera Idempotency-Key (un UUID o ULID de hasta 255 caracteres) con cualquier POST, PATCH o DELETE:

  • La primera petición con una clave se ejecuta y su estado y cuerpo se guardan durante 24 horas.
  • Una repetición con la misma clave y el mismo cuerpo devuelve la respuesta guardada sin volver a ejecutar efectos secundarios.
  • Una repetición con la misma clave pero un cuerpo distinto se rechaza con 409 idempotency_key_conflict.

Úsala en cada llamada que cree algo con efectos secundarios: enviar un mensaje, un email o un SMS, realizar una llamada, cualquier cosa que se facture. Las peticiones GET son siempre idempotentes e ignoran la cabecera.

Los límites se cuentan por minuto y se asocian a la cuenta, la clave de API o el usuario (a la dirección IP en las rutas que no requieren iniciar sesión). Los máximos por defecto:

Cubo Límite por defecto Por minuto
Peticiones sin iniciar sesión (por IP) 60 por IP
Usuario con sesión iniciada (panel) 1 000 por usuario
Clave de API 1 000 por clave
Endpoints públicos del widget 60 por visitante y 600 por dirección de red por minuto
Inicio de sesión (/auth/login) 5 por IP
Webhooks entrantes 300 por minuto
Servidor MCP 600 por minuto
Endpoints de OAuth 600 por minuto

Los máximos son los valores por defecto de la plataforma y el operador puede cambiarlos; tu plan no los multiplica, y los límites de Enterprise se acuerdan en tu contrato. Los endpoints con límite de uso devuelven:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 543

Cuando superas un límite, la respuesta es 429 con code: rate_limited en el array errors y una cabecera Retry-After en segundos. Espera ese tiempo antes de la siguiente llamada. Diez inicios de sesión fallidos bloquean la cuenta durante 30 minutos.

Categoría Cuerpo máximo de la petición Tiempo de espera del servidor
Predeterminado 1 MB 30 s
Mensaje con adjuntos 25 MB 30 s
Importación CSV 50 MB devuelve 202 y se ejecuta en segundo plano
Imágenes de la base de conocimiento 10 MB 30 s
API masiva 10 MB 30 s
Búsqueda 1 MB 10 s
Peticiones de IA 1 MB 60 s
Endpoints del widget 100 KB 30 s

Los cuerpos demasiado grandes reciben 413 payload_too_large. Un servicio de origen que agota el tiempo responde 504 con code: upstream_timeout y una indicación retry_after cuando reintentar puede ayudar.

Tipos de contenido, fechas e identificadores

Sección titulada «Tipos de contenido, fechas e identificadores»
  • Las peticiones y respuestas son application/json; charset=utf-8. Las subidas de archivos usan multipart/form-data; las exportaciones CSV devuelven text/csv. El UTF-8 no válido se rechaza con 400 validation_failed.
  • Las marcas de tiempo son ISO-8601 en UTC con precisión de milisegundos: 2026-04-20T14:23:45.123Z. En la entrada se acepta cualquier desfase ISO-8601, que se normaliza a UTC.
  • Los identificadores son ULID o UUID opacos. No hay identificadores numéricos, y las direcciones de email o los números de teléfono nunca aparecen en una URL.

Cada petición autenticada se ejecuta dentro de una cuenta. Un recurso que pertenece a otra cuenta, o a un sitio que el rol de quien llama no cubre, responde 404 not_found en lugar de 403, para que nunca se filtre la existencia de registros. Un token válido sin el permiso necesario (por ejemplo contacts.delete) responde 403 forbidden. Algunos permisos llevan un sufijo de ámbito (conversations.read:own, :team, :all) que restringe lo que devuelve una lista.

PATCH solo acepta campos modificables. id, account_id, created_at, updated_at y los campos de estado como resolved_at son de solo lectura; enviar uno devuelve 400 validation_failed con details.forbidden_fields. Los cambios de estado pasan por acciones específicas como POST /tickets/:id/resolve.

Cada escritura queda registrada en el registro de auditoría de la cuenta.

Cada respuesta incluye:

X-Request-Id: req_01HK…

Registra X-Request-Id. Es lo primero que pide el equipo de soporte.

El origen del panel en el navegador es https://app.rolchat.com. Los endpoints públicos del widget admiten cualquier origen, o solo los orígenes que verifiques para un sitio. Las llamadas de servidor a servidor con una clave de API no están sujetas a CORS.

  1. El cambio se anuncia en el registro de cambios y el endpoint afectado empieza a enviar Deprecation: true y una cabecera Sunset con la fecha de retirada.
  2. Los endpoints públicos siguen funcionando al menos seis meses después del anuncio.
  3. La retirada solo ocurre en una nueva versión mayor. Dentro de v1 los cambios son aditivos.

Cada servicio expone /healthz (actividad) y /readyz (disponibilidad).