Usuarios y roles
Personas, roles, permisos por persona y restablecimiento de acceso.
GET/usersPágina de personas (search, sort, filter[role], filter[status], filter[mfa])
- Permiso
users.view- Código de quien administra
- —
Cabeceras de la petición
| Cabecera | Valor | Para qué |
|---|---|---|
Authorization | Bearer trazo_… | Token de sesión que entrega el ingreso |
Accept | application/json | La API siempre responde JSON (o un archivo, en la exportación) |
Parámetros
| Nombre | Dónde | Tipo | Obligatorio |
|---|---|---|---|
page | Consulta | entero · ≥ 1 | No |
per_page | Consulta | entero · ≥ 1 · ≤ 100 | No |
sort | Consulta | "name" | "email" | "created_at" | "last_login_at" | "-name" | "-email" | "-created_at" | "-last_login_at" | No |
search | Consulta | texto · máx. 100 | No |
filter[role][] | Consulta | lista de texto | No |
filter[status] | Consulta | "active" | "inactive" | No |
filter[mfa] | Consulta | "enabled" | "disabled" | No |
Respuesta 200
| Campo | Tipo |
|---|---|
data | lista de objeto |
meta | objeto |
meta.page | entero |
meta.per_page | entero |
meta.total | entero |
meta.last_page | entero |
{
"data": [
"texto"
],
"meta": {
"page": 1,
"per_page": 1,
"total": 12,
"last_page": 1
}
}| Cabecera de la respuesta | Para qué |
|---|---|
X-Request-Id | Identificador de la petición; es el trace_id de los errores |
Errores posibles
- 401Sin sesión o la sesión expiró (UNAUTHENTICATED)
- 403Sin permiso para esta acción
- 422Algún dato no es válido (VALIDATION_FAILED, con el detalle por campo)
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.
POST/users201 con la ficha; admite Idempotency-Key
- Permiso
users.create- Código de quien administra
- Si el rol trae permisos sensibles
Cabeceras de la petición
| Cabecera | Valor | Para qué |
|---|---|---|
Authorization | Bearer trazo_… | Token de sesión que entrega el ingreso |
Accept | application/json | La API siempre responde JSON (o un archivo, en la exportación) |
Content-Type | application/json | Cuerpo en JSON |
X-Socket-ID | opcional | Para no recibir en tiempo real el aviso de tu propio cambio |
Cuerpo
| Campo | Tipo | Obligatorio |
|---|---|---|
given_names | texto · máx. 80 | Sí |
family_names | texto · máx. 80 | Sí |
nameNo se envía: el nombre completo lo arma la base | — | No se acepta |
email | texto · email · máx. 191 | Sí |
role | texto | Sí |
mfa_code | texto | null | No |
{
"given_names": "Andrés Castro",
"family_names": "Andrés Castro",
"email": "agente1@trazo.test",
"role": "texto",
"mfa_code": "482913"
}Respuesta 201
| Campo | Tipo |
|---|---|
data | objeto |
data.id | texto |
data.name | texto |
data.given_names | texto |
data.family_names | texto |
data.email | texto |
data.is_active | sí/no |
data.role | objeto | null |
data.role.code | texto |
data.role.name | texto |
data.role.level | entero |
data.mfa_enabled | sí/no |
data.last_login_at | texto | null |
data.created_at | texto |
data.permissions | objeto |
data.permissions.effective | lista de texto |
data.permissions.role | lista de texto |
data.permissions.granted | lista de texto |
data.permissions.denied | lista de texto |
data.pending_assigned_incidents | entero |
data.is_self | sí/no |
data.actions | objeto |
{
"data": {
"id": "01jbzk8m3q9w2e5r7t1y4u6i0p",
"name": "Andrés Castro",
"given_names": "Andrés Castro",
"family_names": "Andrés Castro",
"email": "agente1@trazo.test",
"is_active": true,
"role": {
"code": "in_progress",
"name": "Andrés Castro",
"level": 60
},
"mfa_enabled": true,
"last_login_at": "2026-11-01T14:30:00Z",
"created_at": "2026-11-01T14:30:00Z",
"permissions": {
"effective": [
"texto"
],
"role": [
"texto"
],
"granted": [
"texto"
],
"denied": [
"texto"
]
},
"pending_assigned_incidents": 1,
"is_self": true,
"actions": {}
}
}| Cabecera de la respuesta | Para qué |
|---|---|
X-Request-Id | Identificador de la petición; es el trace_id de los errores |
Errores posibles
- 401Sin sesión o la sesión expiró (UNAUTHENTICATED)
- 403Sin permiso para esta acción
- 422Algún dato no es válido (VALIDATION_FAILED, con el detalle por campo)
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.
GET/users/{user}Ficha con permisos, incidentes pendientes asignados y actions
- Permiso
users.view- Código de quien administra
- —
Cabeceras de la petición
| Cabecera | Valor | Para qué |
|---|---|---|
Authorization | Bearer trazo_… | Token de sesión que entrega el ingreso |
Accept | application/json | La API siempre responde JSON (o un archivo, en la exportación) |
Parámetros
| Nombre | Dónde | Tipo | Obligatorio |
|---|---|---|---|
user | Ruta | texto | Sí |
Respuesta 200
| Campo | Tipo |
|---|---|
data | objeto |
data.id | texto |
data.name | texto |
data.given_names | texto |
data.family_names | texto |
data.email | texto |
data.is_active | sí/no |
data.role | objeto | null |
data.role.code | texto |
data.role.name | texto |
data.role.level | entero |
data.mfa_enabled | sí/no |
data.last_login_at | texto | null |
data.created_at | texto |
data.permissions | objeto |
data.permissions.effective | lista de texto |
data.permissions.role | lista de texto |
data.permissions.granted | lista de texto |
data.permissions.denied | lista de texto |
data.pending_assigned_incidents | entero |
data.is_self | sí/no |
data.actions | objeto |
{
"data": {
"id": "01jbzk8m3q9w2e5r7t1y4u6i0p",
"name": "Andrés Castro",
"given_names": "Andrés Castro",
"family_names": "Andrés Castro",
"email": "agente1@trazo.test",
"is_active": true,
"role": {
"code": "in_progress",
"name": "Andrés Castro",
"level": 60
},
"mfa_enabled": true,
"last_login_at": "2026-11-01T14:30:00Z",
"created_at": "2026-11-01T14:30:00Z",
"permissions": {
"effective": [
"texto"
],
"role": [
"texto"
],
"granted": [
"texto"
],
"denied": [
"texto"
]
},
"pending_assigned_incidents": 1,
"is_self": true,
"actions": {}
}
}| Cabecera de la respuesta | Para qué |
|---|---|
X-Request-Id | Identificador de la petición; es el trace_id de los errores |
Errores posibles
- 401Sin sesión o la sesión expiró (UNAUTHENTICATED)
- 404No existe o quien pregunta no puede verlo
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.
PATCH/users/{user}Ficha; si cambió el correo, avisa a la dirección anterior
- Permiso
users.update- Código de quien administra
- —
Cabeceras de la petición
| Cabecera | Valor | Para qué |
|---|---|---|
Authorization | Bearer trazo_… | Token de sesión que entrega el ingreso |
Accept | application/json | La API siempre responde JSON (o un archivo, en la exportación) |
Content-Type | application/json | Cuerpo en JSON |
X-Socket-ID | opcional | Para no recibir en tiempo real el aviso de tu propio cambio |
Parámetros
| Nombre | Dónde | Tipo | Obligatorio |
|---|---|---|---|
user | Ruta | texto | Sí |
Cuerpo
| Campo | Tipo | Obligatorio |
|---|---|---|
given_names | texto · máx. 80 | Sí |
family_names | texto · máx. 80 | Sí |
nameNo se envía: el nombre completo lo arma la base | — | No se acepta |
email | texto · email · máx. 191 | Sí |
roleNo se envía: el rol tiene su propio endpoint | — | No se acepta |
mfa_codeNo se envía: editar los datos no pide el código de quien administra | — | No se acepta |
{
"given_names": "Andrés Castro",
"family_names": "Andrés Castro",
"email": "agente1@trazo.test"
}Respuesta 200
| Campo | Tipo |
|---|---|
data | objeto |
data.id | texto |
data.name | texto |
data.given_names | texto |
data.family_names | texto |
data.email | texto |
data.is_active | sí/no |
data.role | objeto | null |
data.role.code | texto |
data.role.name | texto |
data.role.level | entero |
data.mfa_enabled | sí/no |
data.last_login_at | texto | null |
data.created_at | texto |
data.permissions | objeto |
data.permissions.effective | lista de texto |
data.permissions.role | lista de texto |
data.permissions.granted | lista de texto |
data.permissions.denied | lista de texto |
data.pending_assigned_incidents | entero |
data.is_self | sí/no |
data.actions | objeto |
{
"data": {
"id": "01jbzk8m3q9w2e5r7t1y4u6i0p",
"name": "Andrés Castro",
"given_names": "Andrés Castro",
"family_names": "Andrés Castro",
"email": "agente1@trazo.test",
"is_active": true,
"role": {
"code": "in_progress",
"name": "Andrés Castro",
"level": 60
},
"mfa_enabled": true,
"last_login_at": "2026-11-01T14:30:00Z",
"created_at": "2026-11-01T14:30:00Z",
"permissions": {
"effective": [
"texto"
],
"role": [
"texto"
],
"granted": [
"texto"
],
"denied": [
"texto"
]
},
"pending_assigned_incidents": 1,
"is_self": true,
"actions": {}
}
}| Cabecera de la respuesta | Para qué |
|---|---|
X-Request-Id | Identificador de la petición; es el trace_id de los errores |
Errores posibles
- 401Sin sesión o la sesión expiró (UNAUTHENTICATED)
- 403Sin permiso para esta acción
- 404No existe o quien pregunta no puede verlo
- 422Algún dato no es válido (VALIDATION_FAILED, con el detalle por campo)
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.
PUT/users/{user}/rolesFicha
- Permiso
users.roles.assign- Código de quien administra
- Si el rol anterior o el nuevo traen permisos sensibles
Cabeceras de la petición
| Cabecera | Valor | Para qué |
|---|---|---|
Authorization | Bearer trazo_… | Token de sesión que entrega el ingreso |
Accept | application/json | La API siempre responde JSON (o un archivo, en la exportación) |
Content-Type | application/json | Cuerpo en JSON |
X-Socket-ID | opcional | Para no recibir en tiempo real el aviso de tu propio cambio |
Parámetros
| Nombre | Dónde | Tipo | Obligatorio |
|---|---|---|---|
user | Ruta | texto | Sí |
Cuerpo
| Campo | Tipo | Obligatorio |
|---|---|---|
mfa_code | texto | null | No |
role | texto | Sí |
{
"mfa_code": "482913",
"role": "texto"
}Respuesta 200
| Campo | Tipo |
|---|---|
data | objeto |
data.id | texto |
data.name | texto |
data.given_names | texto |
data.family_names | texto |
data.email | texto |
data.is_active | sí/no |
data.role | objeto | null |
data.role.code | texto |
data.role.name | texto |
data.role.level | entero |
data.mfa_enabled | sí/no |
data.last_login_at | texto | null |
data.created_at | texto |
data.permissions | objeto |
data.permissions.effective | lista de texto |
data.permissions.role | lista de texto |
data.permissions.granted | lista de texto |
data.permissions.denied | lista de texto |
data.pending_assigned_incidents | entero |
data.is_self | sí/no |
data.actions | objeto |
{
"data": {
"id": "01jbzk8m3q9w2e5r7t1y4u6i0p",
"name": "Andrés Castro",
"given_names": "Andrés Castro",
"family_names": "Andrés Castro",
"email": "agente1@trazo.test",
"is_active": true,
"role": {
"code": "in_progress",
"name": "Andrés Castro",
"level": 60
},
"mfa_enabled": true,
"last_login_at": "2026-11-01T14:30:00Z",
"created_at": "2026-11-01T14:30:00Z",
"permissions": {
"effective": [
"texto"
],
"role": [
"texto"
],
"granted": [
"texto"
],
"denied": [
"texto"
]
},
"pending_assigned_incidents": 1,
"is_self": true,
"actions": {}
}
}| Cabecera de la respuesta | Para qué |
|---|---|
X-Request-Id | Identificador de la petición; es el trace_id de los errores |
Errores posibles
- 401Sin sesión o la sesión expiró (UNAUTHENTICATED)
- 403Sin permiso para esta acción
- 404No existe o quien pregunta no puede verlo
- 422Algún dato no es válido (VALIDATION_FAILED, con el detalle por campo)
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.
PUT/users/{user}/permissionsFicha. Recibe los permisos que debe tener; el back calcula las excepciones
- Permiso
users.permissions.grant- Código de quien administra
- Si cambia un permiso sensible
Cabeceras de la petición
| Cabecera | Valor | Para qué |
|---|---|---|
Authorization | Bearer trazo_… | Token de sesión que entrega el ingreso |
Accept | application/json | La API siempre responde JSON (o un archivo, en la exportación) |
Content-Type | application/json | Cuerpo en JSON |
X-Socket-ID | opcional | Para no recibir en tiempo real el aviso de tu propio cambio |
Parámetros
| Nombre | Dónde | Tipo | Obligatorio |
|---|---|---|---|
user | Ruta | texto | Sí |
Cuerpo
| Campo | Tipo | Obligatorio |
|---|---|---|
mfa_code | texto | null | No |
permissions | lista de texto | Sí |
{
"mfa_code": "482913",
"permissions": [
"texto"
]
}Respuesta 200
| Campo | Tipo |
|---|---|
data | objeto |
data.id | texto |
data.name | texto |
data.given_names | texto |
data.family_names | texto |
data.email | texto |
data.is_active | sí/no |
data.role | objeto | null |
data.role.code | texto |
data.role.name | texto |
data.role.level | entero |
data.mfa_enabled | sí/no |
data.last_login_at | texto | null |
data.created_at | texto |
data.permissions | objeto |
data.permissions.effective | lista de texto |
data.permissions.role | lista de texto |
data.permissions.granted | lista de texto |
data.permissions.denied | lista de texto |
data.pending_assigned_incidents | entero |
data.is_self | sí/no |
data.actions | objeto |
{
"data": {
"id": "01jbzk8m3q9w2e5r7t1y4u6i0p",
"name": "Andrés Castro",
"given_names": "Andrés Castro",
"family_names": "Andrés Castro",
"email": "agente1@trazo.test",
"is_active": true,
"role": {
"code": "in_progress",
"name": "Andrés Castro",
"level": 60
},
"mfa_enabled": true,
"last_login_at": "2026-11-01T14:30:00Z",
"created_at": "2026-11-01T14:30:00Z",
"permissions": {
"effective": [
"texto"
],
"role": [
"texto"
],
"granted": [
"texto"
],
"denied": [
"texto"
]
},
"pending_assigned_incidents": 1,
"is_self": true,
"actions": {}
}
}| Cabecera de la respuesta | Para qué |
|---|---|
X-Request-Id | Identificador de la petición; es el trace_id de los errores |
Errores posibles
- 401Sin sesión o la sesión expiró (UNAUTHENTICATED)
- 403Sin permiso para esta acción
- 404No existe o quien pregunta no puede verlo
- 422Algún dato no es válido (VALIDATION_FAILED, con el detalle por campo)
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.
POST/users/{user}/activateFicha; desactivar cierra sus sesiones al instante
- Permiso
users.activate- Código de quien administra
- —
Cabeceras de la petición
| Cabecera | Valor | Para qué |
|---|---|---|
Authorization | Bearer trazo_… | Token de sesión que entrega el ingreso |
Accept | application/json | La API siempre responde JSON (o un archivo, en la exportación) |
Content-Type | application/json | Cuerpo en JSON |
X-Socket-ID | opcional | Para no recibir en tiempo real el aviso de tu propio cambio |
Parámetros
| Nombre | Dónde | Tipo | Obligatorio |
|---|---|---|---|
user | Ruta | texto | Sí |
Cuerpo
| Campo | Tipo | Obligatorio |
|---|---|---|
mfa_code | texto | null | No |
{
"mfa_code": "482913"
}Respuesta 200
| Campo | Tipo |
|---|---|
data | objeto |
data.id | texto |
data.name | texto |
data.given_names | texto |
data.family_names | texto |
data.email | texto |
data.is_active | sí/no |
data.role | objeto | null |
data.role.code | texto |
data.role.name | texto |
data.role.level | entero |
data.mfa_enabled | sí/no |
data.last_login_at | texto | null |
data.created_at | texto |
data.permissions | objeto |
data.permissions.effective | lista de texto |
data.permissions.role | lista de texto |
data.permissions.granted | lista de texto |
data.permissions.denied | lista de texto |
data.pending_assigned_incidents | entero |
data.is_self | sí/no |
data.actions | objeto |
{
"data": {
"id": "01jbzk8m3q9w2e5r7t1y4u6i0p",
"name": "Andrés Castro",
"given_names": "Andrés Castro",
"family_names": "Andrés Castro",
"email": "agente1@trazo.test",
"is_active": true,
"role": {
"code": "in_progress",
"name": "Andrés Castro",
"level": 60
},
"mfa_enabled": true,
"last_login_at": "2026-11-01T14:30:00Z",
"created_at": "2026-11-01T14:30:00Z",
"permissions": {
"effective": [
"texto"
],
"role": [
"texto"
],
"granted": [
"texto"
],
"denied": [
"texto"
]
},
"pending_assigned_incidents": 1,
"is_self": true,
"actions": {}
}
}| Cabecera de la respuesta | Para qué |
|---|---|
X-Request-Id | Identificador de la petición; es el trace_id de los errores |
Errores posibles
- 401Sin sesión o la sesión expiró (UNAUTHENTICATED)
- 403Sin permiso para esta acción
- 404No existe o quien pregunta no puede verlo
- 422Algún dato no es válido (VALIDATION_FAILED, con el detalle por campo)
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.
POST/users/{user}/deactivateFicha; desactivar cierra sus sesiones al instante
- Permiso
users.activate- Código de quien administra
- —
Cabeceras de la petición
| Cabecera | Valor | Para qué |
|---|---|---|
Authorization | Bearer trazo_… | Token de sesión que entrega el ingreso |
Accept | application/json | La API siempre responde JSON (o un archivo, en la exportación) |
Content-Type | application/json | Cuerpo en JSON |
X-Socket-ID | opcional | Para no recibir en tiempo real el aviso de tu propio cambio |
Parámetros
| Nombre | Dónde | Tipo | Obligatorio |
|---|---|---|---|
user | Ruta | texto | Sí |
Cuerpo
| Campo | Tipo | Obligatorio |
|---|---|---|
mfa_code | texto | null | No |
{
"mfa_code": "482913"
}Respuesta 200
| Campo | Tipo |
|---|---|
data | objeto |
data.id | texto |
data.name | texto |
data.given_names | texto |
data.family_names | texto |
data.email | texto |
data.is_active | sí/no |
data.role | objeto | null |
data.role.code | texto |
data.role.name | texto |
data.role.level | entero |
data.mfa_enabled | sí/no |
data.last_login_at | texto | null |
data.created_at | texto |
data.permissions | objeto |
data.permissions.effective | lista de texto |
data.permissions.role | lista de texto |
data.permissions.granted | lista de texto |
data.permissions.denied | lista de texto |
data.pending_assigned_incidents | entero |
data.is_self | sí/no |
data.actions | objeto |
{
"data": {
"id": "01jbzk8m3q9w2e5r7t1y4u6i0p",
"name": "Andrés Castro",
"given_names": "Andrés Castro",
"family_names": "Andrés Castro",
"email": "agente1@trazo.test",
"is_active": true,
"role": {
"code": "in_progress",
"name": "Andrés Castro",
"level": 60
},
"mfa_enabled": true,
"last_login_at": "2026-11-01T14:30:00Z",
"created_at": "2026-11-01T14:30:00Z",
"permissions": {
"effective": [
"texto"
],
"role": [
"texto"
],
"granted": [
"texto"
],
"denied": [
"texto"
]
},
"pending_assigned_incidents": 1,
"is_self": true,
"actions": {}
}
}| Cabecera de la respuesta | Para qué |
|---|---|
X-Request-Id | Identificador de la petición; es el trace_id de los errores |
Errores posibles
- 401Sin sesión o la sesión expiró (UNAUTHENTICATED)
- 403Sin permiso para esta acción
- 404No existe o quien pregunta no puede verlo
- 422Algún dato no es válido (VALIDATION_FAILED, con el detalle por campo)
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.
DELETE/users/{user}/mfaFicha
- Permiso
users.mfa.reset- Código de quien administra
- Siempre
Cabeceras de la petición
| Cabecera | Valor | Para qué |
|---|---|---|
Authorization | Bearer trazo_… | Token de sesión que entrega el ingreso |
Accept | application/json | La API siempre responde JSON (o un archivo, en la exportación) |
X-Socket-ID | opcional | Para no recibir en tiempo real el aviso de tu propio cambio |
Parámetros
| Nombre | Dónde | Tipo | Obligatorio |
|---|---|---|---|
user | Ruta | texto | Sí |
mfa_code | Consulta | texto | null | No |
Respuesta 200
| Campo | Tipo |
|---|---|
data | objeto |
data.id | texto |
data.name | texto |
data.given_names | texto |
data.family_names | texto |
data.email | texto |
data.is_active | sí/no |
data.role | objeto | null |
data.role.code | texto |
data.role.name | texto |
data.role.level | entero |
data.mfa_enabled | sí/no |
data.last_login_at | texto | null |
data.created_at | texto |
data.permissions | objeto |
data.permissions.effective | lista de texto |
data.permissions.role | lista de texto |
data.permissions.granted | lista de texto |
data.permissions.denied | lista de texto |
data.pending_assigned_incidents | entero |
data.is_self | sí/no |
data.actions | objeto |
{
"data": {
"id": "01jbzk8m3q9w2e5r7t1y4u6i0p",
"name": "Andrés Castro",
"given_names": "Andrés Castro",
"family_names": "Andrés Castro",
"email": "agente1@trazo.test",
"is_active": true,
"role": {
"code": "in_progress",
"name": "Andrés Castro",
"level": 60
},
"mfa_enabled": true,
"last_login_at": "2026-11-01T14:30:00Z",
"created_at": "2026-11-01T14:30:00Z",
"permissions": {
"effective": [
"texto"
],
"role": [
"texto"
],
"granted": [
"texto"
],
"denied": [
"texto"
]
},
"pending_assigned_incidents": 1,
"is_self": true,
"actions": {}
}
}| Cabecera de la respuesta | Para qué |
|---|---|
X-Request-Id | Identificador de la petición; es el trace_id de los errores |
Errores posibles
- 401Sin sesión o la sesión expiró (UNAUTHENTICATED)
- 403Sin permiso para esta acción
- 404No existe o quien pregunta no puede verlo
- 422Algún dato no es válido (VALIDATION_FAILED, con el detalle por campo)
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.
POST/users/{user}/access-resetFicha
- Permiso
users.access.reset- Código de quien administra
- Siempre
Cabeceras de la petición
| Cabecera | Valor | Para qué |
|---|---|---|
Authorization | Bearer trazo_… | Token de sesión que entrega el ingreso |
Accept | application/json | La API siempre responde JSON (o un archivo, en la exportación) |
Content-Type | application/json | Cuerpo en JSON |
X-Socket-ID | opcional | Para no recibir en tiempo real el aviso de tu propio cambio |
Parámetros
| Nombre | Dónde | Tipo | Obligatorio |
|---|---|---|---|
user | Ruta | texto | Sí |
Cuerpo
| Campo | Tipo | Obligatorio |
|---|---|---|
mfa_code | texto | null | No |
{
"mfa_code": "482913"
}Respuesta 200
| Campo | Tipo |
|---|---|
data | objeto |
data.id | texto |
data.name | texto |
data.given_names | texto |
data.family_names | texto |
data.email | texto |
data.is_active | sí/no |
data.role | objeto | null |
data.role.code | texto |
data.role.name | texto |
data.role.level | entero |
data.mfa_enabled | sí/no |
data.last_login_at | texto | null |
data.created_at | texto |
data.permissions | objeto |
data.permissions.effective | lista de texto |
data.permissions.role | lista de texto |
data.permissions.granted | lista de texto |
data.permissions.denied | lista de texto |
data.pending_assigned_incidents | entero |
data.is_self | sí/no |
data.actions | objeto |
{
"data": {
"id": "01jbzk8m3q9w2e5r7t1y4u6i0p",
"name": "Andrés Castro",
"given_names": "Andrés Castro",
"family_names": "Andrés Castro",
"email": "agente1@trazo.test",
"is_active": true,
"role": {
"code": "in_progress",
"name": "Andrés Castro",
"level": 60
},
"mfa_enabled": true,
"last_login_at": "2026-11-01T14:30:00Z",
"created_at": "2026-11-01T14:30:00Z",
"permissions": {
"effective": [
"texto"
],
"role": [
"texto"
],
"granted": [
"texto"
],
"denied": [
"texto"
]
},
"pending_assigned_incidents": 1,
"is_self": true,
"actions": {}
}
}| Cabecera de la respuesta | Para qué |
|---|---|
X-Request-Id | Identificador de la petición; es el trace_id de los errores |
Errores posibles
- 401Sin sesión o la sesión expiró (UNAUTHENTICATED)
- 403Sin permiso para esta acción
- 404No existe o quien pregunta no puede verlo
- 422Algún dato no es válido (VALIDATION_FAILED, con el detalle por campo)
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.
GET/rolesRoles de mayor a menor nivel, con permisos, política de MFA, personas que lo tienen, si quien consulta lo puede dar (assignable) y actions
- Permiso
users.vieworoles.manage- Código de quien administra
- —
Cabeceras de la petición
| Cabecera | Valor | Para qué |
|---|---|---|
Authorization | Bearer trazo_… | Token de sesión que entrega el ingreso |
Accept | application/json | La API siempre responde JSON (o un archivo, en la exportación) |
Respuesta 200
| Campo | Tipo |
|---|---|
data | lista de objeto |
{
"data": [
"texto"
]
}| Cabecera de la respuesta | Para qué |
|---|---|
X-Request-Id | Identificador de la petición; es el trace_id de los errores |
Errores posibles
- 401Sin sesión o la sesión expiró (UNAUTHENTICATED)
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.
GET/roles/{role}Un rol
- Permiso
users.vieworoles.manage- Código de quien administra
- —
Cabeceras de la petición
| Cabecera | Valor | Para qué |
|---|---|---|
Authorization | Bearer trazo_… | Token de sesión que entrega el ingreso |
Accept | application/json | La API siempre responde JSON (o un archivo, en la exportación) |
Parámetros
| Nombre | Dónde | Tipo | Obligatorio |
|---|---|---|---|
role | Ruta | texto | Sí |
Respuesta 200
| Campo | Tipo |
|---|---|
data | objeto |
data.code | texto |
data.name | texto |
data.level | entero |
data.is_system | sí/no |
data.permissions | lista de texto |
data.mfa | objeto |
data.mfa.required | sí/no |
data.mfa.grace_logins | entero |
data.members | entero |
data.assignable | sí/no |
data.actions | objeto |
{
"data": {
"code": "in_progress",
"name": "Andrés Castro",
"level": 60,
"is_system": true,
"permissions": [
"texto"
],
"mfa": {
"required": true,
"grace_logins": 1
},
"members": 1,
"assignable": true,
"actions": {}
}
}| Cabecera de la respuesta | Para qué |
|---|---|
X-Request-Id | Identificador de la petición; es el trace_id de los errores |
Errores posibles
- 401Sin sesión o la sesión expiró (UNAUTHENTICATED)
- 404No existe o quien pregunta no puede verlo
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.
POST/roles201 con el rol; admite Idempotency-Key
- Permiso
roles.manage- Código de quien administra
- Si trae permisos sensibles
Cabeceras de la petición
| Cabecera | Valor | Para qué |
|---|---|---|
Authorization | Bearer trazo_… | Token de sesión que entrega el ingreso |
Accept | application/json | La API siempre responde JSON (o un archivo, en la exportación) |
Content-Type | application/json | Cuerpo en JSON |
X-Socket-ID | opcional | Para no recibir en tiempo real el aviso de tu propio cambio |
Cuerpo
| Campo | Tipo | Obligatorio |
|---|---|---|
code | texto · mín. 3 · máx. 40 | Sí |
name | texto · mín. 2 · máx. 80 | Sí |
level | entero · ≥ 1 · ≤ 99 | Sí |
permissions | lista de texto | Sí |
mfa_required | sí/no | Sí |
grace_logins | entero · ≥ 0 · ≤ 5 | Sí |
mfa_code | texto | null | No |
{
"code": "in_progress",
"name": "Andrés Castro",
"level": 60,
"permissions": [
"texto"
],
"mfa_required": true,
"grace_logins": 0,
"mfa_code": "482913"
}Respuesta 201
| Campo | Tipo |
|---|---|
data | objeto |
data.code | texto |
data.name | texto |
data.level | entero |
data.is_system | sí/no |
data.permissions | lista de texto |
data.mfa | objeto |
data.mfa.required | sí/no |
data.mfa.grace_logins | entero |
data.members | entero |
data.assignable | sí/no |
data.actions | objeto |
{
"data": {
"code": "in_progress",
"name": "Andrés Castro",
"level": 60,
"is_system": true,
"permissions": [
"texto"
],
"mfa": {
"required": true,
"grace_logins": 1
},
"members": 1,
"assignable": true,
"actions": {}
}
}| Cabecera de la respuesta | Para qué |
|---|---|
X-Request-Id | Identificador de la petición; es el trace_id de los errores |
Errores posibles
- 401Sin sesión o la sesión expiró (UNAUTHENTICATED)
- 403Sin permiso para esta acción
- 422Algún dato no es válido (VALIDATION_FAILED, con el detalle por campo)
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.
PATCH/roles/{role}El rol
- Permiso
roles.manage- Código de quien administra
- Si cambian permisos sensibles, el nivel o la política de MFA se vuelve más permisiva
Cabeceras de la petición
| Cabecera | Valor | Para qué |
|---|---|---|
Authorization | Bearer trazo_… | Token de sesión que entrega el ingreso |
Accept | application/json | La API siempre responde JSON (o un archivo, en la exportación) |
Content-Type | application/json | Cuerpo en JSON |
X-Socket-ID | opcional | Para no recibir en tiempo real el aviso de tu propio cambio |
Parámetros
| Nombre | Dónde | Tipo | Obligatorio |
|---|---|---|---|
role | Ruta | texto | Sí |
Cuerpo
| Campo | Tipo | Obligatorio |
|---|---|---|
codeNo se envía: el código de un rol no cambia | — | No se acepta |
name | texto · mín. 2 · máx. 80 | Sí |
level | entero · ≥ 1 · ≤ 99 | Sí |
permissions | lista de texto | Sí |
mfa_required | sí/no | Sí |
grace_logins | entero · ≥ 0 · ≤ 5 | Sí |
mfa_code | texto | null | No |
{
"name": "Andrés Castro",
"level": 60,
"permissions": [
"texto"
],
"mfa_required": true,
"grace_logins": 0,
"mfa_code": "482913"
}Respuesta 200
| Campo | Tipo |
|---|---|
data | objeto |
data.code | texto |
data.name | texto |
data.level | entero |
data.is_system | sí/no |
data.permissions | lista de texto |
data.mfa | objeto |
data.mfa.required | sí/no |
data.mfa.grace_logins | entero |
data.members | entero |
data.assignable | sí/no |
data.actions | objeto |
{
"data": {
"code": "in_progress",
"name": "Andrés Castro",
"level": 60,
"is_system": true,
"permissions": [
"texto"
],
"mfa": {
"required": true,
"grace_logins": 1
},
"members": 1,
"assignable": true,
"actions": {}
}
}| Cabecera de la respuesta | Para qué |
|---|---|
X-Request-Id | Identificador de la petición; es el trace_id de los errores |
Errores posibles
- 401Sin sesión o la sesión expiró (UNAUTHENTICATED)
- 403Sin permiso para esta acción
- 404No existe o quien pregunta no puede verlo
- 422Algún dato no es válido (VALIDATION_FAILED, con el detalle por campo)
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.
DELETE/roles/{role}204; solo un rol creado que nadie tiene
- Permiso
roles.manage- Código de quien administra
- —
Cabeceras de la petición
| Cabecera | Valor | Para qué |
|---|---|---|
Authorization | Bearer trazo_… | Token de sesión que entrega el ingreso |
Accept | application/json | La API siempre responde JSON (o un archivo, en la exportación) |
X-Socket-ID | opcional | Para no recibir en tiempo real el aviso de tu propio cambio |
Parámetros
| Nombre | Dónde | Tipo | Obligatorio |
|---|---|---|---|
role | Ruta | texto | Sí |
Respuesta 204
Sin cuerpo: la operación salió bien.
| Cabecera de la respuesta | Para qué |
|---|---|
X-Request-Id | Identificador de la petición; es el trace_id de los errores |
Errores posibles
- 401Sin sesión o la sesión expiró (UNAUTHENTICATED)
- 404No existe o quien pregunta no puede verlo
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.
GET/permissionsPermisos con su módulo, si son sensibles y si quien consulta los puede conceder (grantable)
- Permiso
users.vieworoles.manage- Código de quien administra
- —
Cabeceras de la petición
| Cabecera | Valor | Para qué |
|---|---|---|
Authorization | Bearer trazo_… | Token de sesión que entrega el ingreso |
Accept | application/json | La API siempre responde JSON (o un archivo, en la exportación) |
Respuesta 200
| Campo | Tipo |
|---|---|
data | lista de objeto |
{
"data": [
"texto"
]
}| Cabecera de la respuesta | Para qué |
|---|---|
X-Request-Id | Identificador de la petición; es el trace_id de los errores |
Errores posibles
- 401Sin sesión o la sesión expiró (UNAUTHENTICATED)
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.