QAPI está en beta — la API puede cambiar sin previo aviso. Usa sandbox para pruebas.
QAPIQAPIDocs · by DTEVIA
Api

Refrescar tokens

Renueva el access token usando el refresh token de la cookie HttpOnly `qapi_rt` (no se envía en el body). Devuelve un nuevo access token y **rota la cookie** del refresh. 🛡️ **CSRF**: como la cookie se adjunta automáticamente, este endpoint exige protección double-submit. Enviá el header `X-CSRF-Token` con el valor de la cookie no-HttpOnly `qapi_csrf`. ⚠️ **Rotación**: el refresh anterior queda revocado. Si se reutiliza un refresh ya rotado, QAPI lo detecta como posible robo y **revoca todas las sesiones del usuario**.

POST
/v1/auth/refresh

Header Parameters

X-CSRF-Token*string

Debe coincidir con el valor de la cookie qapi_csrf (double-submit).

Response Body

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/v1/auth/refresh" \  -H "X-CSRF-Token: string"
{
  "access_token": "string"
}
{
  "type": "https://docs.dtevia.com.gt/errors/validation-error",
  "title": "VALIDATION_ERROR",
  "status": 422,
  "detail": "Error de validación",
  "instance": "/v1/invoices",
  "invalid_params": [
    {
      "field": "items.0.impuestos.0.monto_impuesto",
      "message": "MontoImpuesto IVA inválido. Esperado ~12 (MontoGravable 100 × 0.12), recibido 10"
    }
  ]
}
{
  "type": "https://docs.dtevia.com.gt/errors/validation-error",
  "title": "VALIDATION_ERROR",
  "status": 422,
  "detail": "Error de validación",
  "instance": "/v1/invoices",
  "invalid_params": [
    {
      "field": "items.0.impuestos.0.monto_impuesto",
      "message": "MontoImpuesto IVA inválido. Esperado ~12 (MontoGravable 100 × 0.12), recibido 10"
    }
  ]
}
{
  "type": "https://docs.dtevia.com.gt/errors/validation-error",
  "title": "VALIDATION_ERROR",
  "status": 422,
  "detail": "Error de validación",
  "instance": "/v1/invoices",
  "invalid_params": [
    {
      "field": "items.0.impuestos.0.monto_impuesto",
      "message": "MontoImpuesto IVA inválido. Esperado ~12 (MontoGravable 100 × 0.12), recibido 10"
    }
  ]
}

Iniciar sesión

Autentica con email y contraseña. Devuelve el `access_token` (JWT) junto con el perfil del usuario y del tenant. El `refresh_token` NO viene en el body: QAPI lo setea en una cookie HttpOnly `qapi_rt` (inaccesible a JavaScript). 💡 **Guardá el `access_token`**: es el que vas a usar como `Authorization: Bearer <token>` para probar los endpoints de **Sandbox** desde esta misma documentación. Dura **15 minutos**; renovalo con `POST /v1/auth/refresh` (que usa la cookie). 🔐 **MFA**: si la cuenta tiene verificación en dos pasos activa (obligatoria para superadmin), este endpoint NO devuelve tokens — responde `{ "mfa_required": true, "mfa_token": "..." }` (o `mfa_enrollment_required` si el superadmin aún no lo configuró). Completá el login con `POST /v1/auth/mfa/verify`. > Para **integrar tu software** con QAPI usá una **API key**, no este flujo JWT (pensado para el dashboard en el navegador). Protegido contra fuerza bruta: máximo 10 intentos por email cada 15 minutos.

Cerrar sesión

Cierra la sesión: revoca el refresh token de la cookie HttpOnly `qapi_rt` y limpia las cookies de auth. El access token sigue siendo válido hasta su expiración (15 min) — descartalo del lado del cliente (o se invalida al instante si la sesión está en la denylist). 🛡️ **CSRF**: igual que /refresh, exige el header `X-CSRF-Token` con el valor de la cookie `qapi_csrf`. Si enviás tu `Authorization: Bearer <access_token>`, QAPI verifica que el refresh pertenezca a tu usuario antes de revocarlo.