Descripción General
La API de Usuarios permite gestionar empleados de tu empresa con estados activo e inactivo, basándose en sus asignaciones a centros de costos y subsidiarias.
Estado de Usuario
Un usuario puede estar en uno de dos estados:
- Activo (
is_active: true
): Tiene acceso para reportar gastos a través de asignaciones a centros de costos - Inactivo (
is_active: false
): No tiene asignaciones activas y no puede reportar gastos
El campo is_active
es calculado automáticamente por el sistema basándose en las asignaciones del usuario.
Endpoints
Base URL
https://api.xpendit.com/public/v1/enterprises/{enterprise_id}/users
Reemplaza {enterprise_id}
con el ID de tu empresa.
1. Crear Usuario
Crea un nuevo usuario en tu empresa.
Endpoint
POST /public/v1/enterprises/{enterprise_id}/users/
Headers
Content-Type: application/json
Authorization: Api-Key en_sk_xxxxx
Parámetros del Body
Campo | Tipo | Requerido | Descripción |
---|---|---|---|
first_name | string | No | Nombre del usuario |
last_name | string | No | Apellido del usuario |
email | string | Condicional | Email del usuario |
phone | string | Condicional | Teléfono en formato E164 (ej: +56912345678) |
government_id | string | No | RUT u otro identificador gubernamental |
internal_id | string | No | Identificador interno de tu sistema |
allocations | array | No | Asignaciones a subsidiarias y centros de costos |
* Al menos uno de email
o phone
es requerido
Estructura de Allocations
{
"allocations": [
{
"subsidiary_id": "uuid", // O usar subsidiary_internal_id
"is_responsible": false, // Opcional
"user_manager_id": "uuid", // O usar user_manager_internal_id. Opcional
"cost_centers": [ // Opcional. Si está vacío, se asigna a TODOS
{
"id": "uuid", // O usar internal_id
"is_responsible": false // Opcional
}
]
}
]
}
Ejemplo: Crear Usuario Inactivo
POST /public/v1/enterprises/660e8400-e29b-41d4-a716-446655440000/users/
Content-Type: application/json
Authorization: Api-Key en_sk_xxxxx
{
"first_name": "Juan",
"last_name": "Pérez",
"email": "[email protected]",
"phone": "+56912345678",
"government_id": "12345678-9",
"internal_id": "EMP-001",
"allocations": []
}
Response 201 Created:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"first_name": "Juan",
"last_name": "Pérez",
"email": "[email protected]",
"phone": "+56912345678",
"government_id": "12345678-9",
"internal_id": "EMP-001",
"enterprise_id": "660e8400-e29b-41d4-a716-446655440000",
"is_active": false,
"created_at": "2025-10-08T10:00:00Z",
"updated_at": "2025-10-08T10:00:00Z"
}
Ejemplo: Crear Usuario Activo
POST /public/v1/enterprises/660e8400-e29b-41d4-a716-446655440000/users/
Content-Type: application/json
Authorization: Api-Key en_sk_xxxxx
{
"first_name": "María",
"last_name": "López",
"email": "[email protected]",
"phone": "+56987654321",
"allocations": [
{
"subsidiary_id": "770e8400-e29b-41d4-a716-446655440000",
"cost_centers": [
{
"id": "990e8400-e29b-41d4-a716-446655440000",
"is_responsible": true
}
]
}
]
}
Response 201 Created:
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"first_name": "María",
"last_name": "López",
"email": "[email protected]",
"phone": "+56987654321",
"enterprise_id": "660e8400-e29b-41d4-a716-446655440000",
"is_active": true,
"created_at": "2025-10-08T10:05:00Z",
"updated_at": "2025-10-08T10:05:00Z"
}
Comportamiento Especial de Cost Centers
cost_centers
vacío o no especificado: El usuario se asigna automáticamente a TODOS los centros de costos activos de la subsidiariacost_centers
con IDs específicos: El usuario se asigna solo a esos centros de costos
2. Obtener Usuario
Obtiene la información detallada de un usuario específico.
Endpoint
GET /public/v1/enterprises/{enterprise_id}/users/{user_id}/
Query Parameters
Parámetro | Tipo | Descripción |
---|---|---|
expand | string | Campos adicionales a incluir. Valores:enterprise |
Ejemplo
GET /public/v1/enterprises/660e8400-e29b-41d4-a716-446655440000/users/550e8400-e29b-41d4-a716-446655440000/
Authorization: Api-Key en_sk_xxxxx
Response 200 OK:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"first_name": "Juan",
"last_name": "Pérez",
"email": "[email protected]",
"phone": "+56912345678",
"government_id": "12345678-9",
"internal_id": "EMP-001",
"enterprise_id": "660e8400-e29b-41d4-a716-446655440000",
"is_active": true,
"created_at": "2025-10-08T10:00:00Z",
"updated_at": "2025-10-08T10:15:00Z",
"status": 200,
"error": ""
}
Ejemplo con Expand
GET /public/v1/enterprises/660e8400-e29b-41d4-a716-446655440000/users/550e8400-e29b-41d4-a716-446655440000/?expand=enterprise
Authorization: Api-Key en_sk_xxxxx
Response 200 OK:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"first_name": "Juan",
"last_name": "Pérez",
"email": "[email protected]",
"is_active": true,
"enterprise_id": "660e8400-e29b-41d4-a716-446655440000",
"enterprise": {
"id": "660e8400-e29b-41d4-a716-446655440000",
"name": "Empresa Demo",
"legal_name": "Empresa Demo S.A.",
"internal_id": "ENT-001",
"created_at": "2025-01-01T00:00:00Z"
},
"created_at": "2025-10-08T10:00:00Z",
"updated_at": "2025-10-08T10:00:00Z",
"status": 200,
"error": ""
}
3. Listar Usuarios
Obtiene la lista paginada de usuarios de tu empresa.
Endpoint
GET /public/v1/enterprises/{enterprise_id}/users/
Query Parameters
Parámetro | Tipo | Descripción |
---|---|---|
status | string | Filtrar por estado. Valores:active , inactive |
email | string | Filtrar por email exacto |
phone | string | Filtrar por teléfono (con o sin +) |
expand | string | Campos adicionales. Valores:enterprise |
page | integer | Número de página (inicia en 1) |
page_size | integer | Cantidad de resultados por página (máx: 100) |
Ejemplo: Todos los Usuarios
GET /public/v1/enterprises/660e8400-e29b-41d4-a716-446655440000/users/
Authorization: Api-Key en_sk_xxxxx
Response 200 OK:
{
"count": 25,
"next": "https://api.xpendit.com/public/v1/enterprises/660e8400-e29b-41d4-a716-446655440000/users/?page=2",
"previous": null,
"results": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"first_name": "Juan",
"last_name": "Pérez",
"email": "[email protected]",
"phone": "+56912345678",
"is_active": true,
"created_at": "2025-10-08T10:00:00Z",
"updated_at": "2025-10-08T10:00:00Z"
}
]
}
Ejemplo: Solo Usuarios Activos
GET /public/v1/enterprises/660e8400-e29b-41d4-a716-446655440000/users/?status=active
Authorization: Api-Key en_sk_xxxxx
Ejemplo: Solo Usuarios Inactivos
GET /public/v1/enterprises/660e8400-e29b-41d4-a716-446655440000/users/?status=inactive
Authorization: Api-Key en_sk_xxxxx
Ejemplo: Buscar por Email
GET /public/v1/enterprises/660e8400-e29b-41d4-a716-446655440000/users/[email protected]
Authorization: Api-Key en_sk_xxxxx
Ejemplo: Buscar por Teléfono
GET /public/v1/enterprises/660e8400-e29b-41d4-a716-446655440000/users/?phone=+56912345678
Authorization: Api-Key en_sk_xxxxx
4. Actualizar Usuario
Actualiza la información de un usuario existente.
Endpoint
PATCH /public/v1/enterprises/{enterprise_id}/users/{user_id}/
Headers
Content-Type: application/json
Authorization: Api-Key en_sk_xxxxx
Campos Actualizables
Campo | Tipo | Descripción |
---|---|---|
first_name | string | Nombre del usuario |
last_name | string | Apellido del usuario |
email | string | Email del usuario |
phone | string | Teléfono en formato E164 |
government_id | string | Identificador gubernamental |
internal_id | string | Identificador interno |
allocations | array | Asignaciones (reemplaza las existentes) |
Campos Read-Only (No Modificables)
id
enterprise_id
is_active
(se calcula automáticamente)created_at
updated_at
Ejemplo: Actualizar Datos Personales
PATCH /public/v1/enterprises/660e8400-e29b-41d4-a716-446655440000/users/550e8400-e29b-41d4-a716-446655440000/
Content-Type: application/json
Authorization: Api-Key en_sk_xxxxx
{
"first_name": "Juan Carlos",
"last_name": "Pérez González",
"phone": "+56912345999",
"email": "[email protected]"
}
Response 200 OK:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"first_name": "Juan Carlos",
"last_name": "Pérez González",
"email": "[email protected]",
"phone": "+56912345999",
"government_id": "12345678-9",
"internal_id": "EMP-001",
"enterprise_id": "660e8400-e29b-41d4-a716-446655440000",
"is_active": true,
"created_at": "2025-10-08T10:00:00Z",
"updated_at": "2025-10-08T12:30:00Z"
}
Nota: Si no incluyes el campo allocations
, las asignaciones actuales del usuario no se modifican.
Ejemplo: Activar Usuario (Agregar Allocations)
PATCH /public/v1/enterprises/660e8400-e29b-41d4-a716-446655440000/users/550e8400-e29b-41d4-a716-446655440000/
Content-Type: application/json
Authorization: Api-Key en_sk_xxxxx
{
"allocations": [
{
"subsidiary_id": "770e8400-e29b-41d4-a716-446655440000",
"cost_centers": [
{
"id": "990e8400-e29b-41d4-a716-446655440000"
}
]
}
]
}
Response 200 OK:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"first_name": "Juan Carlos",
"last_name": "Pérez González",
"email": "[email protected]",
"is_active": true,
"created_at": "2025-10-08T10:00:00Z",
"updated_at": "2025-10-08T12:35:00Z"
}
El campo is_active
cambia automáticamente a true
cuando se asignan centros de costos.
Ejemplo: Inactivar Usuario (Remover Allocations)
PATCH /public/v1/enterprises/660e8400-e29b-41d4-a716-446655440000/users/550e8400-e29b-41d4-a716-446655440001/
Content-Type: application/json
Authorization: Api-Key en_sk_xxxxx
{
"allocations": []
}
Response 200 OK:
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"first_name": "María",
"last_name": "López",
"email": "[email protected]",
"is_active": false,
"created_at": "2025-10-08T10:05:00Z",
"updated_at": "2025-10-08T12:40:00Z"
}
El campo is_active
cambia automáticamente a false
cuando se eliminan todas las asignaciones.
Nota Importante: Al enviar allocations: []
, el sistema automáticamente:
- ✅ Revoca todos los permisos de centros de costos
- ✅ Elimina todas las responsabilidades de centros de costos
- ✅ Desactiva el rol EMPLOYEE en todas las subsidiarias
- ✅ Elimina todas las responsabilidades de subsidiarias
El usuario quedará completamente desvinculado de todas las áreas y sin permisos para reportar gastos.
Ejemplo: Cambiar Asignaciones (Transferir de Departamento)
PATCH /public/v1/enterprises/660e8400-e29b-41d4-a716-446655440000/users/550e8400-e29b-41d4-a716-446655440001/
Content-Type: application/json
Authorization: Api-Key en_sk_xxxxx
{
"allocations": [
{
"subsidiary_id": "880e8400-e29b-41d4-a716-446655440000",
"is_responsible": true,
"cost_centers": [
{
"id": "aa0e8400-e29b-41d4-a716-446655440000",
"is_responsible": true
},
{
"id": "bb0e8400-e29b-41d4-a716-446655440000",
"is_responsible": false
}
]
}
]
}
Nota: El array allocations
reemplaza completamente las asignaciones existentes. Incluye todas las subsidiarias y centros de costos que deseas mantener.
5. Uso de Internal IDs
Puedes usar internal_id
en lugar de UUIDs para referenciar entidades. Esto es útil para integrar con tus sistemas internos.
Ejemplo Completo con Internal IDs
POST /public/v1/enterprises/660e8400-e29b-41d4-a716-446655440000/users/
Content-Type: application/json
Authorization: Api-Key en_sk_xxxxx
{
"first_name": "Carlos",
"last_name": "Ramírez",
"email": "[email protected]",
"internal_id": "EMP-002",
"allocations": [
{
"subsidiary_internal_id": "SUBS-001",
"user_manager_internal_id": "EMP-001",
"cost_centers": [
{
"internal_id": "CC-VENTAS",
"is_responsible": true
},
{
"internal_id": "CC-MARKETING",
"is_responsible": false
}
]
}
]
}
Reglas de Uso
- ✅ Puedes usar
id
(UUID) Ointernal_id
para cada entidad - ❌ No mezcles ambos para la misma entidad
- ✅ Puedes combinar: usar UUID para subsidiaria e internal_id para cost centers
Casos de Uso Comunes
1. Onboarding de Empleado Nuevo
# Paso 1: Crear usuario sin asignaciones (inactivo)
POST /public/v1/enterprises/{enterprise_id}/users/
{
"email": "[email protected]",
"first_name": "Nuevo",
"last_name": "Empleado",
"allocations": []
}
# Paso 2: Cuando esté listo, activar con asignaciones
PATCH /public/v1/enterprises/{enterprise_id}/users/{user_id}/
{
"allocations": [
{
"subsidiary_id": "...",
"cost_centers": [{"id": "..."}]
}
]
}
2. Transferencia de Departamento
PATCH /public/v1/enterprises/{enterprise_id}/users/{user_id}/
{
"allocations": [
{
"subsidiary_id": "nueva-subsidiaria-id",
"cost_centers": [
{"id": "nuevo-centro-costos-id"}
]
}
]
}
3. Suspensión Temporal de Usuario
PATCH /public/v1/enterprises/{enterprise_id}/users/{user_id}/
{
"allocations": []
}
Esto inactiva al usuario sin eliminarlo del sistema.
4. Actualización de Datos sin Afectar Permisos
PATCH /public/v1/enterprises/{enterprise_id}/users/{user_id}/
{
"first_name": "Nombre Actualizado",
"email": "[email protected]",
"phone": "+56999999999"
}
No incluyas allocations
para mantener las asignaciones actuales.
Validaciones y Restricciones
Formato de Teléfono
Los teléfonos deben estar en formato E164:
- ✅ Correcto:
+56912345678
- ✅ Correcto:
56912345678
(se acepta sin +) - ❌ Incorrecto:
9 1234 5678
- ❌ Incorrecto:
(569) 1234-5678
Formato de Email
- Debe ser un email válido:
[email protected]
- Es case-sensitive (diferencia mayúsculas/minúsculas)
Unicidad
email
: Debe ser único globalmente en toda la plataformaphone
: Debe ser único globalmente en toda la plataformainternal_id
: Puede repetirse entre diferentes empresas
Restricciones de Allocations
- Las subsidiarias deben pertenecer a tu empresa
- Los centros de costos deben pertenecer a la subsidiaria especificada
- El manager debe pertenecer a la misma subsidiaria
- No se permite asignar recursos de otras empresas
Códigos de Estado HTTP
Código | Descripción |
---|---|
200 OK | Operación exitosa (GET, PATCH) |
201 Created | Usuario creado exitosamente (POST) |
400 Bad Request | Datos inválidos en la petición |
401 Unauthorized | API Key inválida o faltante |
403 Forbidden | No tienes permisos para esta operación |
404 Not Found | Usuario no encontrado |
500 Internal Server Error | Error del servidor |
Manejo de Errores
Ejemplo de Error 400
{
"phone": [
"A user with this phone number already exists."
]
}
Ejemplo de Error 404
{
"detail": "Not found."
}
Ejemplo de Error 400 con Validaciones de Allocations
{
"allocations": [
{
"cost_centers": [
"Cost centers {'aa0e8400-e29b-41d4-a716-446655440000'} do not belong to the specified subsidiary."
]
}
]
}
Límites de la API
- Rate Limiting: Consulta con tu representante de Xpendit
- Page Size Máximo: 100 resultados por página
- Timeout: 30 segundos por petición
Comportamiento del Campo is_active
El campo is_active
es calculado automáticamente y no puede ser modificado directamente.
¿Cuándo es un usuario activo?
Un usuario es activo cuando tiene al menos una asignación a un centro de costos que le permita reportar gastos.
Cambios Automáticos
- ✅ Agregar allocations →
is_active
cambia atrue
- ✅ Eliminar todas las allocations →
is_active
cambia afalse
- ✅ Modificar allocations →
is_active
se actualiza según corresponda
Importante
- El estado se calcula en tiempo real con cada petición
- No se almacena en base de datos, siempre es el estado actual
- No intentes enviar
is_active
en POST o PATCH, será ignorado