Ir al contenido

API y OpenAPI

Asientra expone una API REST versionada (/api/v1/...) consumida por la SPA y disponible para integraciones externas. Usa JWT bearer auth con aislamiento multi-tenant garantizado por RLS.

La spec viva está en asientra-api/openapi.yaml, generada desde rswag y actualizada en cada cambio de contrato. Importala en Postman, Insomnia o cualquier cliente OpenAPI 3.

| Endpoint | Descripción | |---|---| | POST /api/v1/auth/login | Retorna access_token (15 min) + refresh_token (7 días) | | POST /api/v1/auth/refresh | Rota el refresh y emite nuevo par de tokens | | DELETE /api/v1/auth/logout | Revoca el refresh token |

Incluí el access token en cada request:

Authorization: Bearer <access_token>

Los roles owner, admin y contador_senior requieren 2FA en el login. El campo two_factor_code va en el mismo body que email y password.

Todo request a recursos tenant-scoped requiere el header:

X-Despacho-Id: <despacho_id>

El middleware verifica que el usuario tenga membresía activa en ese despacho, luego ejecuta SET LOCAL app.current_despacho_id = <id> en la conexión Postgres. RLS filtra automáticamente todas las queries subsiguientes.

  • Cambios breaking → nueva versión /api/v2/. La v1 se mantiene activa durante el periodo de migración.
  • Cambios aditivos/api/v1/ con nuevos campos opcionales. No rompen clientes existentes.

Todos los endpoints de colección aceptan:

GET /api/v1/clientes?page=2&per_page=25

La respuesta incluye un objeto meta:

{
"data": [...],
"meta": {
"total": 120,
"page": 2,
"per_page": 25,
"total_pages": 5
}
}
GET /api/v1/facturas?filter[estado]=aceptado&sort=-fecha_emision,consecutivo

-campo = orden descendente. Múltiples campos separados por coma.

Formato JSON:API:

{
"errors": [
{
"status": "422",
"code": "partida_doble_violation",
"title": "Error de validación",
"detail": "La suma de débitos (₡1.000) no coincide con la suma de créditos (₡900)."
}
]
}

Códigos HTTP estándar: 400 (bad request), 401 (sin token / token vencido), 403 (sin permiso), 404 (recurso no encontrado), 422 (validación de negocio), 429 (rate limit), 500 (error interno).

Rack::Attack limita requests por IP y por token. Al superar el límite, la respuesta es 429 Too Many Requests con el header Retry-After: <segundos>.