Documentación
Alcance y scopes
Las tres capas que deciden qué puede hacer una credencial — y por qué te dio 403.
Una credencial no otorga acceso: lo recorta. Actúa siempre en nombre de la persona que la creó, con sus permisos y su licencia, y los scopes solo achican ese alcance. Nunca lo amplían.
lo que el USUARIO puede hacer hoy
∩
los SCOPES del access token
∩
los RECURSOS que la credencial alcanza
─────────────────────────────────────
= lo que este request puede hacerLas tres capas se evalúan en cada request, contra el estado vivo. No hay foto congelada del día del alta.
1. Los permisos del usuario
Es el techo. Si al rol del usuario le quitan skills.update.own, el scope skills:write de todas sus credenciales deja de valer en el request siguiente, sin tocar ninguna credencial. No hace falta buscarlas ni revocarlas una por una.
Lo mismo vale hacia arriba: si le dan un permiso nuevo, las credenciales que ya tenían ese scope concedido empiezan a poder usarlo. Por eso GET /me puede devolver scopes distintos de un día para otro con el mismo token.
2. Los scopes del token
Cada operación declara el scope que exige. Falta uno y la respuesta es 403 con WWW-Authenticate: Bearer error="insufficient_scope", scope="…", que nombra exactamente cuál falta.
| Scope | Qué habilita | Permisos que lo respaldan |
|---|---|---|
chat:read | Listar y leer chats, mensajes y el catálogo de recursos del chat. | sidebar.chat |
chat:write | Crear chats, enviar turnos, responder interacciones y renombrar o borrar chats. Consume el pool de niucredits de la licencia del usuario. | sidebar.chat |
areas:read | Listar y leer las áreas visibles para el usuario. | areas.read.all, areas.read.area |
skills:read | Listar y leer habilidades. | skills.read.all, skills.read.area, skills.read.own |
skills:write | Crear, editar, activar/desactivar y eliminar habilidades. | skills.create, skills.create.public, skills.create.shared, skills.update.all, skills.update.own, skills.delete.all, skills.delete.own |
rules:read | Listar y leer reglas de la organización. | rules.read |
rules:write | Crear, editar, activar/desactivar y eliminar reglas. | rules.create.company, rules.create.area, rules.update, rules.delete |
permissions:read | Consultar roles, el catálogo de permisos y los permisos efectivos del usuario. | roles.read |
libraries:read | Listar y leer bibliotecas y sus archivos. | workspaces.read.all, workspaces.read.area, workspaces.read.own |
libraries:write | Crear y editar bibliotecas. No incluye subir ni eliminar archivos. | workspaces.create, workspaces.update.all, workspaces.update.area, workspaces.update.own |
connectors:use | Consultar el catálogo de conectores y permitir que el chat ejecute sus herramientas. No autoriza conectores nuevos: usa los que el usuario ya conectó. | mcps.read.all, mcps.read.area |
profile:read | Consultar el perfil del usuario en cuyo nombre actúa la credencial. | — (opera sobre el propio perfil) |
profile:write | Actualizar datos del perfil del usuario en cuyo nombre actúa la credencial. | — (opera sobre el propio perfil) |
users:read | Listar los usuarios de la empresa (id, nombre, correo, estado y áreas). Necesario para armar shared_user_ids al compartir una habilidad. | users.read.all, users.read.area |
analytics:read | Consultar métricas de uso y consumo de tokens. | metrics.read.all, metrics.read.area |
Nota
Basta uno de los permisos listados para que el scope sea concedible. skills:write cubre crear, editar y borrar; un rol que solo pueda crear igual necesita el scope. El permiso fino se vuelve a verificar dentro de la operación — el scope es la primera capa, nunca la única.
3. Los recursos
Una credencial puede además estar acotada a bibliotecas, habilidades, áreas o conectores concretos. Ver Credenciales para cómo se configura.
Un recurso fuera del alcance responde `404`, no `403`, cuando el cliente no lo nombró explícitamente. Un 403 confirmaría que el recurso existe, y con ids secuenciales eso alcanza para inventariar lo ajeno.
La excepción es cuando el cliente sí lo nombró: un area_id en una regla, un workspace_id en una habilidad. Ahí la respuesta es 403 api_v1_resource_not_allowed, porque fingir que no existe algo que el cliente acaba de pedir sería confuso y no protege nada.
Scopes compañeros del chat
chat:write autoriza conversar, no leer lo que se adjunte. Adjuntar un recurso a un turno exige además el scope de lectura de ese recurso:
| Adjunto | Scope adicional |
|---|---|
attachments.workspace_ids | libraries:read |
attachments.file_ids | libraries:read |
attachments.skill_ids | skills:read |
attachments.mcp_server_ids | connectors:use |
Atención
Sin esta regla, chat:write sola alcanzaría para que el modelo leyera el contenido de una biblioteca que la credencial no puede abrir: el turno sería el canal de fuga. La validación ocurre antes de reservar la idempotencia, así que un 403 acá no consume tu key.
Qué herramientas ve el modelo
En un turno de la API, el modelo recibe un conjunto acotado de herramientas internas, decidido por los mismos scopes:
| Herramienta | Requiere |
|---|---|
list_workspaces, list_documents, search_documents | libraries:read |
ask_user_choice | — (produce una interacción) |
submit_plan, update_plan | — (reportan progreso) |
search_tools | — |
Nota
Es una lista de permitidos, no de prohibidos: una capacidad nueva de la plataforma no entra sola a un turno de la API. Las herramientas que vuelven a entrar a NiuCore con la sesión del usuario quedan fuera de la v1.0, porque en un turno delegado esa sesión no existe.
Los conectores (Gmail, Drive, Calendar…) sí funcionan, con connectors:use, pero solo los que el usuario ya conectó desde la aplicación. La API no puede autorizar un conector nuevo: eso necesita un navegador y una persona.
Diagnosticar un 403
- Llamá a
GET /me.scopesdice con qué estás operando de verdad, ypermissionspor qué. - Si el scope está en la credencial pero no en
scopes, al usuario le falta el permiso que lo respalda. - Si el scope está y el
403persiste, es la capa de recursos: la credencial está acotada y ese recurso quedó afuera. - En un turno, revisá
data.required_scopes: nombra el scope compañero que falta para el adjunto que mandaste.