Endpoints de lectura: canales y mensajes
Lista los canales a los que tu aplicación tiene acceso, sus miembros y sus mensajes visibles, con paginación por cursor y búsqueda.
Actualizado el . 5 min de lectura
Incluido en todos los planes. Ver precios
Con estos endpoints tu aplicación consulta los canales donde tiene acceso, quién está en ellos y qué se ha dicho, por ejemplo para tener contexto antes de responder o para resolver el contenido de un aviso que acaba de recibir.
| Endpoint | Scope |
|---|---|
GET /api/external/v1/chat/channels | chat:channels:view |
GET /api/external/v1/chat/channels/:channelId | chat:channels:view |
GET /api/external/v1/chat/channels/:channelId/members | chat:channels:view |
GET /api/external/v1/chat/channels/:channelId/messages | chat:messages:view |
GET /api/external/v1/chat/messages/:messageId | chat:messages:view |
Como al publicar, se cumplen las dos puertas de Scopes y acceso por canal: sin el scope, 403 INSUFFICIENT_SCOPE; sin concesión activa en el canal, 404 (CHANNEL_NOT_FOUND o MESSAGE_NOT_FOUND), sin revelar si el canal o el mensaje existen.
Solo mensajes visibles
Tu aplicación solo recibe mensajes públicos o dirigidos a los participantes del canal. Nunca los marcados como internos del equipo, los privados, las respuestas privadas de la IA ni los eliminados. El filtro se aplica igual en el listado, en el detalle y en la búsqueda.
Paginación por cursor
Los listados de canales y de mensajes van del más reciente al más antiguo y se paginan por cursor. Cada respuesta trae un bloque pagination:
- nextCursorstring | null
- Cursor de la página siguiente; null si no hay más.
- hasMoreboolean
- Si quedan más elementos.
- limitnumber
- Tamaño de página aplicado: de 1 a 100, 50 por defecto.
Para recorrer todo, repite la llamada con el nextCursor recibido en el parámetro cursor hasta que hasMore sea false:
Recorrer el historial de un canal
Participan: Tu aplicación, UTILIA OS.
De Tu aplicación a UTILIA OS:
GET .../channels/:channelId/messages?limit=50
Primera página, sin cursor.De UTILIA OS a Tu aplicación:
50 mensajes, hasMore true (respuesta)
Del más reciente al más antiguo, con nextCursor.De Tu aplicación a UTILIA OS:
GET ...?limit=50&cursor=nextCursor
La página siguiente, más antigua.De UTILIA OS a Tu aplicación:
Últimos mensajes, hasMore false (respuesta)
nextCursor es null: no queda nada más.
Listar canales
/api/external/v1/chat/channelsLista los canales donde la app tiene una concesión activa y es participante
Devuelve solo los canales donde tu aplicación tiene una concesión activa y sigue siendo miembro.
Parámetros de consulta
- limitnumber
- Tamaño de página, de 1 a 100. Por defecto 50
- cursorstring
- El nextCursor de la página anterior.
Respuesta (200)
Objeto con data (lista de canales) y pagination. Cada canal tiene esta forma:
- idstring
- Identificador del canal (conversación)
- typestring
- Tipo de canal: CHANNEL o GROUP
- namestring | null
- Nombre del canal
- descriptionstring | null
- Descripción del canal
- isDiscoverableboolean
- Si el canal aparece en el directorio de canales de la organización
- lastMessageAtstring | null
- Fecha del último mensaje, en formato ISO 8601
- createdAtstring
- Fecha de creación del canal, en formato ISO 8601
curl 'https://os.utilia.ai/api/external/v1/chat/channels?limit=20' \
-H 'X-Api-Key: utl_tu_clave_de_api'{
"data": [
{
"id": "cnv_8f3a21",
"type": "CHANNEL",
"name": "Sala de servidores",
"description": "Alertas y lecturas de la sala técnica",
"isDiscoverable": true,
"lastMessageAt": "2026-07-12T09:00:03.512Z",
"createdAt": "2026-06-01T10:15:00.000Z"
}
],
"pagination": { "nextCursor": null, "hasMore": false, "limit": 20 }
}Detalle de un canal
/api/external/v1/chat/channels/:channelIdDetalle de un canal concedido
Parámetros de ruta
- channelIdstringobligatorio
- Identificador del canal (conversación)
Devuelve el mismo objeto de canal. Sin concesión activa, o si el canal es de otra organización, responde 404 CHANNEL_NOT_FOUND.
Miembros de un canal
/api/external/v1/chat/channels/:channelId/membersLista los miembros de un canal concedido
Devuelve una lista sin paginar con los miembros del canal. Distingue los cuatro tipos de miembro sin exponer datos sensibles como los correos.
Parámetros de ruta
- channelIdstringobligatorio
- Identificador del canal (conversación)
Respuesta (200)
Cada miembro tiene esta forma:
- kindstring
- Tipo de miembro: USER (persona del equipo), PORTAL_USER (usuario del portal del cliente), AGENT (agente de IA) o APP (app externa)
- idstring
- Identificador del miembro
- displayNamestring
- Nombre del miembro tal como aparece en el canal
- rolestring
- Rol en el canal: OWNER, ADMIN o MEMBER
[
{ "kind": "USER", "id": "usr_12ab", "displayName": "Lucía Pérez", "role": "OWNER" },
{ "kind": "APP", "id": "app_termometro", "displayName": "Termómetro", "role": "MEMBER" }
]Mensajes de un canal
/api/external/v1/chat/channels/:channelId/messagesLista los mensajes visibles de un canal concedido, con paginación por cursor
Devuelve los mensajes visibles del canal, del más reciente al más antiguo.
Parámetros de ruta
- channelIdstringobligatorio
- Identificador del canal (conversación)
Parámetros de consulta
- cursorstring
- El nextCursor de la página anterior.
- limitnumber
- Tamaño de página, de 1 a 100. Por defecto 50
- searchstring
- Texto a buscar en los mensajes visibles. Hasta 200 caracteres
Respuesta (200)
Objeto con data (lista de mensajes) y pagination. Cada mensaje tiene la misma forma que la respuesta de la publicación:
- idstring
- Identificador del mensaje
- channelIdstring
- Identificador del canal donde se publicó
- contentstring | null
- Contenido del mensaje
- typestring
- Tipo de mensaje (por ejemplo TEXT)
- authorobject
- Autor del mensaje: { kind, id, displayName }. kind es USER, AGENT o APP
- parentMessageIdstring | null
- Mensaje al que responde, si forma parte de un hilo
- mentionsstring[]
- Identificadores mencionados en el mensaje
- createdAtstring
- Fecha de creación en formato ISO 8601
- editedAtstring | null
- Fecha de la última edición, o null
- isDeletedboolean
- Siempre false en la salida (los eliminados no se devuelven)
curl 'https://os.utilia.ai/api/external/v1/chat/channels/cnv_8f3a21/messages?limit=50' \
-H 'X-Api-Key: utl_tu_clave_de_api'{
"data": [
{
"id": "msg_a1b2c3d4",
"channelId": "cnv_8f3a21",
"content": "Temperatura de la sala de servidores: 21,4 °C",
"type": "TEXT",
"author": { "kind": "APP", "id": "app_termometro", "displayName": "Termómetro" },
"parentMessageId": null,
"mentions": [],
"createdAt": "2026-07-12T09:00:03.512Z",
"editedAt": null,
"isDeleted": false
}
],
"pagination": { "nextCursor": "msg_a1b2c3d4", "hasMore": true, "limit": 50 }
}Detalle de un mensaje
/api/external/v1/chat/messages/:messageIdDetalle de un mensaje visible de un canal concedido
Parámetros de ruta
- messageIdstringobligatorio
- Identificador del mensaje
Devuelve el mensaje si es visible para tu aplicación y su canal tiene concesión activa. Si no existe, no es visible o su canal no tiene concesión, responde 404 MESSAGE_NOT_FOUND, sin distinguir el caso.
Es la llamada que necesitas al recibir un webhook: el aviso CHAT_MESSAGE_CREATED solo trae el messageId, y con él obtienes aquí el contenido, ya filtrado.
Errores
| Código | errorCode | Cuándo |
|---|---|---|
| 401 | La clave de API falta o no es válida. | |
| 403 | MODULE_NOT_ENABLED | El plan de tu organización no incluye el Chat. |
| 403 | INSUFFICIENT_SCOPE | Falta el scope de lectura. |
| 404 | CHANNEL_NOT_FOUND | El canal no existe, es de otra organización o no hay concesión activa. |
| 404 | MESSAGE_NOT_FOUND | El mensaje no existe, no es visible o su canal no tiene concesión activa. |
Siguiente paso
En lugar de consultar cada poco, deja que UTILIA OS te avise: webhooks de chat. Los mismos endpoints, con tipos, están en el SDK del chat.