Imagy Identity — API Reference
Servicios
Identity expone APIs a traves de dos servicios. El Gateway maneja autenticacion y proxy; Management maneja CRUD de recursos.
| Servicio | Base URL | Autenticacion |
|---|---|---|
| Gateway (BFF) | https://{tenant}.reimaginetech.io/bff/ | Cookie de sesion |
| Management | https://api.{tenant}.reimaginetech.io/api/v1/ | JWT Bearer |
Identity Gateway — Endpoints BFF
Estos endpoints son consumidos por el frontend para gestionar la sesion del usuario.
Iniciar Login
GET /bff/loginInicia el flujo OIDC + PKCE. Redirige al usuario a la pantalla de login de Keycloak.
Query params:
| Parametro | Tipo | Descripcion |
|---|---|---|
return_url | STRING | URL a la que redirigir despues del login (default: /) |
Response: 302 Redirect a Keycloak Authorization Endpoint
Callback OIDC
GET /bff/callbackEndpoint de callback que recibe el authorization code de Keycloak, lo intercambia por tokens y crea la sesion.
Response: 302 Redirect a return_url con cookie session_id establecida.
Obtener Sesion
GET /bff/session
Cookie: session_id={value}Retorna informacion de la sesion activa (usuario, tenant, roles). Usado por el frontend para verificar estado de autenticacion.
Response 200:
{
"data": {
"is_authenticated": true,
"user": {
"id": "user-uuid-001",
"email": "admin@fintech-abc.com",
"name": "Carlos Admin",
"roles": ["tenant_admin", "operator"]
},
"tenant": {
"id": "tenant-uuid-001",
"name": "Fintech ABC",
"slug": "fintech-abc"
},
"organization": {
"id": "org-uuid-001",
"name": "Sucursal Quito"
},
"expires_in_seconds": 1500
}
}Response 401: Sesion expirada o invalida.
Logout
POST /bff/logout
Cookie: session_id={value}Cierra la sesion: elimina de Redis, revoca tokens en Keycloak, limpia cookie.
Response 200:
{
"data": {
"logged_out": true,
"redirect_url": "https://fintech-abc.reimaginetech.io"
}
}Refresh Token
POST /bff/refresh
Cookie: session_id={value}Renueva el access_token usando el refresh_token almacenado en la sesion. El frontend no necesita invocar esto manualmente — el Gateway lo hace automaticamente cuando detecta un token proximo a expirar.
Response 200:
{
"data": {
"refreshed": true,
"expires_in_seconds": 1800
}
}Identity Management — Endpoints de Tenants
Listar Tenants
GET /api/v1/tenants
Authorization: Bearer {jwt}Solo accesible por platform_admin y delegated_admin.
Query params:
| Parametro | Tipo | Descripcion |
|---|---|---|
page | INT | Pagina (default: 1) |
page_size | INT | Resultados por pagina (default: 20, max: 100) |
status | STRING | Filtrar por estado (active, suspended, onboarding) |
search | STRING | Buscar por nombre o slug |
Response 200:
{
"data": [
{
"id": "tenant-uuid-001",
"name": "Fintech ABC",
"slug": "fintech-abc",
"status": "active",
"plan": "professional",
"user_count": 15,
"created_at": "2026-01-15T08:00:00Z"
}
],
"metadata": {
"pagination": { "page": 1, "page_size": 20, "total": 5, "total_pages": 1 }
}
}Crear Tenant
POST /api/v1/tenants
Authorization: Bearer {jwt}
Idempotency-Key: {uuid}Crea un nuevo tenant: registro en BD, realm en Keycloak, usuario admin inicial.
Request Body:
{
"name": "Fintech XYZ",
"slug": "fintech-xyz",
"plan": "starter",
"config": {
"timezone": "America/Bogota",
"locale": "es-CO",
"currency": "COP"
},
"admin_user": {
"email": "admin@fintech-xyz.com",
"first_name": "Maria",
"last_name": "Admin"
}
}Response 201:
{
"data": {
"id": "tenant-uuid-002",
"name": "Fintech XYZ",
"slug": "fintech-xyz",
"status": "active",
"realm_name": "fintech-xyz",
"admin_user_id": "user-uuid-010",
"created_at": "2026-05-18T10:00:00Z"
}
}Obtener Tenant
GET /api/v1/tenants/{id}
Authorization: Bearer {jwt}Response 200: Detalle completo del tenant incluyendo config, theme y modules.
Actualizar Tenant
PATCH /api/v1/tenants/{id}
Authorization: Bearer {jwt}
If-Match: "{etag}"Actualiza configuracion, tema o estado del tenant.
Suspender Tenant
POST /api/v1/tenants/{id}/suspend
Authorization: Bearer {jwt}Suspende un tenant. Los usuarios no pueden autenticarse mientras esta suspendido.
Identity Management — Endpoints de Usuarios
Listar Usuarios
GET /api/v1/users
Authorization: Bearer {jwt}Lista usuarios del tenant actual (determinado por JWT).
Query params:
| Parametro | Tipo | Descripcion |
|---|---|---|
page | INT | Pagina |
page_size | INT | Resultados por pagina |
status | STRING | Filtrar por estado |
role | STRING | Filtrar por rol |
organization_id | UUID | Filtrar por organizacion |
search | STRING | Buscar por nombre o email |
Crear Usuario
POST /api/v1/users
Authorization: Bearer {jwt}
Idempotency-Key: {uuid}Crea un usuario en el tenant actual y en el realm de Keycloak.
Request Body:
{
"email": "juan.perez@fintech-abc.com",
"first_name": "Juan",
"last_name": "Perez",
"phone": "+593991234567",
"roles": ["operator"],
"organization_id": "org-uuid-001",
"send_welcome_email": true
}Response 201:
{
"data": {
"id": "user-uuid-020",
"email": "juan.perez@fintech-abc.com",
"first_name": "Juan",
"last_name": "Perez",
"status": "pending_verification",
"roles": ["operator"],
"created_at": "2026-05-18T10:30:00Z"
}
}Obtener / Actualizar / Desactivar Usuario
GET /api/v1/users/{id}
PATCH /api/v1/users/{id}
DELETE /api/v1/users/{id}DELETE realiza soft-delete (status → inactive).
Identity Management — Endpoints de Roles
CRUD de Roles
GET /api/v1/roles
POST /api/v1/roles
GET /api/v1/roles/{id}
PATCH /api/v1/roles/{id}
DELETE /api/v1/roles/{id}Solo tenant_admin puede gestionar roles. Los roles de sistema (is_system = true) no pueden ser editados ni eliminados.
Identity Management — Endpoints de Organizaciones
CRUD de Organizaciones
GET /api/v1/organizations
POST /api/v1/organizations
GET /api/v1/organizations/{id}
PATCH /api/v1/organizations/{id}
DELETE /api/v1/organizations/{id}Las organizaciones se sincronizan con Keycloak Organizations API.
Endpoints Internos (Service-to-Service)
Consumidos por otros microservicios con JWT propagado.
Crear Usuario (interno — para pipeline de credito)
POST /internal/users
X-Service-Auth: {service_token}Crea un usuario en el realm del tenant sin requerir JWT de admin. Usado por ImagLend en el step user_registration del pipeline.
Request Body:
{
"tenant_id": "tenant-uuid-001",
"email": "solicitante@email.com",
"first_name": "Maria",
"last_name": "Garcia",
"phone": "+593991234567",
"document_type": "cc",
"document_number": "1234567890",
"role": "applicant",
"send_credentials": true
}Response 201:
{
"data": {
"user_id": "user-uuid-030",
"keycloak_id": "kc-uuid-030",
"temporary_password": "auto-generated",
"must_change_password": true
}
}Verificar Tenant Activo
GET /internal/tenants/{id}/status
X-Service-Auth: {service_token}Verifica si un tenant esta activo. Usado por servicios antes de procesar requests.
Response 200:
{
"data": {
"tenant_id": "tenant-uuid-001",
"status": "active",
"modules": ["imagflow", "imaglend", "imagsign"]
}
}Resolver Tenant por Slug
GET /internal/tenants/resolve?slug={slug}
X-Service-Auth: {service_token}Resuelve un slug a tenant_id. Usado por el Gateway para tenant routing.
Codigos de Error
| Codigo | HTTP | Descripcion |
|---|---|---|
VALIDATION_ERROR | 400 | Datos invalidos |
UNAUTHORIZED | 401 | No autenticado o sesion expirada |
FORBIDDEN | 403 | Sin permisos para la operacion |
NOT_FOUND | 404 | Recurso no encontrado |
CONFLICT | 409 | Slug duplicado, email duplicado, rol duplicado |
PRECONDITION_FAILED | 412 | ETag mismatch (concurrencia) |
TENANT_SUSPENDED | 403 | Tenant suspendido, no se permiten operaciones |
MAX_USERS_REACHED | 422 | Limite de usuarios del plan alcanzado |
REALM_CREATION_FAILED | 502 | Error al crear realm en Keycloak |
INTERNAL_ERROR | 500 | Error interno |
Headers
| Header | Direccion | Descripcion |
|---|---|---|
Authorization | Request | Bearer {JWT} |
Cookie: session_id | Request | Sesion BFF (solo endpoints /bff/) |
Idempotency-Key | Request (POST) | UUID para idempotencia |
If-Match | Request (PATCH) | ETag para concurrencia optimista |
ETag | Response | Version del recurso |
X-Request-Id | Response | ID de trazabilidad |
X-Service-Auth | Request (internal) | Token de servicio para endpoints internos |