Sesión y acceso
Ingreso, verificación en dos pasos, recuperación y cambio de contraseña.
POST/auth/loginToken, vencimiento y usuario
- Sesión
- No
- Límite
- 5 por minuto (correo + IP)
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 |
|---|---|---|
email | texto · email · máx. 191 | Sí |
password | texto · máx. 255 | Sí |
{
"email": "agente1@trazo.test",
"password": "••••••••••••"
}Respuesta 200
| Campo | Tipo |
|---|---|
data | objeto |
data.status | texto |
data.token | texto |
data.token_type | texto |
data.expires_at | texto |
data.user | objeto | null |
data.user.id | texto |
data.user.name | texto |
data.user.email | texto |
data.user.roles | lista de objeto |
data.user.permissions | lista de texto |
data.user.mfa | objeto |
{
"data": {
"status": "in_progress",
"token": "trazo_…",
"token_type": "trazo_…",
"expires_at": "2026-11-01T14:30:00Z",
"user": {
"id": "01jbzk8m3q9w2e5r7t1y4u6i0p",
"name": "Andrés Castro",
"email": "agente1@trazo.test",
"roles": [
{
"code": "in_progress",
"name": "Andrés Castro"
}
],
"permissions": [
"texto"
],
"mfa": {
"enabled": true,
"required": true,
"recovery_codes_left": 1
}
}
}
}| Cabecera de la respuesta | Para qué |
|---|---|
X-Request-Id | Identificador de la petición; es el trace_id de los errores |
Retry-After | En un 429: segundos para volver a intentar |
Errores posibles
- 401Sin sesión o la sesión expiró (UNAUTHENTICATED)
- 422Algún dato no es válido (VALIDATION_FAILED, con el detalle por campo)
- 429Demasiadas peticiones (TOO_MANY_REQUESTS, con Retry-After)
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.
POST/auth/logout204 y el token queda revocado
- Sesión
- Sí
- Límite
- General
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 |
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)
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.
GET/auth/meUsuario con roles, permisos y estado del MFA
- Sesión
- Sí
- Límite
- General
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 | objeto |
data.id | texto |
data.name | texto |
data.email | texto |
data.roles | lista de objeto |
data.roles[].code | texto |
data.roles[].name | texto |
data.permissions | lista de texto |
data.mfa | objeto |
data.mfa.enabled | sí/no |
data.mfa.required | sí/no |
data.mfa.recovery_codes_left | entero |
{
"data": {
"id": "01jbzk8m3q9w2e5r7t1y4u6i0p",
"name": "Andrés Castro",
"email": "agente1@trazo.test",
"roles": [
{
"code": "in_progress",
"name": "Andrés Castro"
}
],
"permissions": [
"texto"
],
"mfa": {
"enabled": true,
"required": true,
"recovery_codes_left": 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)
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.
POST/auth/mfa/verifySegundo paso: code o recovery_code; devuelve la sesión completa
- Sesión
- Ingreso a medias
- Límite
- 5 por minuto
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 | No |
recovery_code | texto · máx. 20 | No |
{
"code": "in_progress",
"recovery_code": "texto"
}Respuesta 200
| Campo | Tipo |
|---|---|
data | objeto |
data.status | texto |
data.token | texto |
data.token_type | texto |
data.expires_at | texto |
data.user | objeto | null |
data.user.id | texto |
data.user.name | texto |
data.user.email | texto |
data.user.roles | lista de objeto |
data.user.permissions | lista de texto |
data.user.mfa | objeto |
{
"data": {
"status": "in_progress",
"token": "trazo_…",
"token_type": "trazo_…",
"expires_at": "2026-11-01T14:30:00Z",
"user": {
"id": "01jbzk8m3q9w2e5r7t1y4u6i0p",
"name": "Andrés Castro",
"email": "agente1@trazo.test",
"roles": [
{
"code": "in_progress",
"name": "Andrés Castro"
}
],
"permissions": [
"texto"
],
"mfa": {
"enabled": true,
"required": true,
"recovery_codes_left": 1
}
}
}
}| Cabecera de la respuesta | Para qué |
|---|---|
X-Request-Id | Identificador de la petición; es el trace_id de los errores |
Retry-After | En un 429: segundos para volver a intentar |
Errores posibles
- 401Sin sesión o la sesión expiró (UNAUTHENTICATED)
- 422Algún dato no es válido (VALIDATION_FAILED, con el detalle por campo)
- 429Demasiadas peticiones (TOO_MANY_REQUESTS, con Retry-After)
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.
POST/auth/mfa/setupClave nueva sin confirmar y su dirección otpauth:// para el QR
- Sesión
- Ingreso a medias o sesión
- Límite
- General
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 |
Respuesta 200
| Campo | Tipo |
|---|---|
data | objeto |
data.secret | texto |
data.uri | texto |
{
"data": {
"secret": "texto",
"uri": "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.
POST/auth/mfa/setup/confirmActiva el MFA con el primer code; devuelve los 8 códigos de recuperación y, si venía de un ingreso a medias, la sesión completa
- Sesión
- Ingreso a medias o sesión
- Límite
- 5 por minuto
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 | Sí |
{
"code": "in_progress"
}Respuesta 200
| Campo | Tipo |
|---|---|
data | objeto |
data.recovery_codes | lista de objeto |
data.session | objeto | null |
data.session.status | texto |
data.session.token | texto |
data.session.token_type | texto |
data.session.expires_at | texto |
data.session.user | objeto | null |
{
"data": {
"recovery_codes": [
"texto"
],
"session": {
"status": "in_progress",
"token": "trazo_…",
"token_type": "trazo_…",
"expires_at": "2026-11-01T14:30:00Z",
"user": {
"id": "01jbzk8m3q9w2e5r7t1y4u6i0p",
"name": "Andrés Castro",
"email": "agente1@trazo.test",
"roles": [
{
"code": null,
"name": null
}
],
"permissions": [
"texto"
],
"mfa": {
"enabled": true,
"required": true,
"recovery_codes_left": 1
}
}
}
}
}| Cabecera de la respuesta | Para qué |
|---|---|
X-Request-Id | Identificador de la petición; es el trace_id de los errores |
Retry-After | En un 429: segundos para volver a intentar |
Errores posibles
- 401Sin sesión o la sesión expiró (UNAUTHENTICATED)
- 422Algún dato no es válido (VALIDATION_FAILED, con el detalle por campo)
- 429Demasiadas peticiones (TOO_MANY_REQUESTS, con Retry-After)
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.
POST/auth/mfa/recovery-codesCon un code actual, 8 códigos nuevos; los anteriores dejan de servir
- Sesión
- Sí
- Límite
- 5 por minuto
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 | Sí |
{
"code": "in_progress"
}Respuesta 200
| Campo | Tipo |
|---|---|
data | objeto |
data.recovery_codes | lista de objeto |
{
"data": {
"recovery_codes": [
"texto"
]
}
}| Cabecera de la respuesta | Para qué |
|---|---|
X-Request-Id | Identificador de la petición; es el trace_id de los errores |
Retry-After | En un 429: segundos para volver a intentar |
Errores posibles
- 401Sin sesión o la sesión expiró (UNAUTHENTICATED)
- 422Algún dato no es válido (VALIDATION_FAILED, con el detalle por campo)
- 429Demasiadas peticiones (TOO_MANY_REQUESTS, con Retry-After)
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.
DELETE/auth/mfaCon un code actual, desactiva el MFA si la política del rol no lo exige
- Sesión
- Sí
- Límite
- 5 por minuto
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 |
|---|---|---|---|
code | Consulta | 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 |
Retry-After | En un 429: segundos para volver a intentar |
Errores posibles
- 401Sin sesión o la sesión expiró (UNAUTHENTICATED)
- 422Algún dato no es válido (VALIDATION_FAILED, con el detalle por campo)
- 429Demasiadas peticiones (TOO_MANY_REQUESTS, con Retry-After)
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.
POST/auth/password/forgot202 siempre: si el correo es de una cuenta activa, le llega un código
- Sesión
- No
- Límite
- 3 cada 15 minutos (correo + IP)
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 |
|---|---|---|
email | texto · email · máx. 191 | Sí |
{
"email": "agente1@trazo.test"
}Respuesta 202
| Cabecera de la respuesta | Para qué |
|---|---|
X-Request-Id | Identificador de la petición; es el trace_id de los errores |
Retry-After | En un 429: segundos para volver a intentar |
Errores posibles
- 401Sin sesión o la sesión expiró (UNAUTHENTICATED)
- 422Algún dato no es válido (VALIDATION_FAILED, con el detalle por campo)
- 429Demasiadas peticiones (TOO_MANY_REQUESTS, con Retry-After)
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.
POST/auth/password/verify-codeCon email y code, un pase de un solo uso (ticket) y si la cuenta pide segundo factor (mfa_required)
- Sesión
- No
- Límite
- 5 por minuto (correo + IP)
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 |
|---|---|---|
email | texto · email · máx. 191 | Sí |
code | texto | Sí |
{
"email": "agente1@trazo.test",
"code": "in_progress"
}Respuesta 200
| Campo | Tipo |
|---|---|
data | objeto |
data.ticket | texto |
data.mfa_required | sí/no |
{
"data": {
"ticket": "texto",
"mfa_required": true
}
}| Cabecera de la respuesta | Para qué |
|---|---|
X-Request-Id | Identificador de la petición; es el trace_id de los errores |
Retry-After | En un 429: segundos para volver a intentar |
Errores posibles
- 401Sin sesión o la sesión expiró (UNAUTHENTICATED)
- 422Algún dato no es válido (VALIDATION_FAILED, con el detalle por campo)
- 429Demasiadas peticiones (TOO_MANY_REQUESTS, con Retry-After)
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.
POST/auth/password/resetCon email, ticket, password, su confirmación y, si hace falta, mfa_code o recovery_code; 204
- Sesión
- No
- Límite
- 5 por minuto (correo + IP)
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 |
|---|---|---|
email | texto · email · máx. 191 | Sí |
ticket | texto · mín. 64 · máx. 64 | Sí |
passwordSolo el correo que ya trae la petición: buscar el nombre antes de validar el pase revelaría datos de la cuenta | texto · mín. 12 · máx. 128 | Sí |
mfa_code | texto | null | No |
recovery_code | texto | null · máx. 20 | No |
password_confirmation | texto · mín. 12 · máx. 128 | Sí |
{
"email": "agente1@trazo.test",
"ticket": "texto",
"password": "••••••••••••",
"mfa_code": "482913",
"recovery_code": "texto",
"password_confirmation": "••••••••••••"
}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 |
Retry-After | En un 429: segundos para volver a intentar |
Errores posibles
- 401Sin sesión o la sesión expiró (UNAUTHENTICATED)
- 422Algún dato no es válido (VALIDATION_FAILED, con el detalle por campo)
- 429Demasiadas peticiones (TOO_MANY_REQUESTS, con Retry-After)
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.
PUT/auth/passwordCon current_password, password y su confirmación; 204
- Sesión
- Sí
- Límite
- 5 por minuto por persona
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 |
|---|---|---|
current_password | texto · máx. 255 | Sí |
password | texto · mín. 12 · máx. 128 | Sí |
password_confirmation | texto · mín. 12 · máx. 128 | Sí |
{
"current_password": "••••••••••••",
"password": "••••••••••••",
"password_confirmation": "••••••••••••"
}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 |
Retry-After | En un 429: segundos para volver a intentar |
Errores posibles
- 401Sin sesión o la sesión expiró (UNAUTHENTICATED)
- 422Algún dato no es válido (VALIDATION_FAILED, con el detalle por campo)
- 429Demasiadas peticiones (TOO_MANY_REQUESTS, con Retry-After)
Todos llegan en formato RFC 9457 con su code y trace_id: ver Errores de la API.