Skip to content

API keys ​

Gestión de API keys a nivel de tenant. Crea llaves nombradas para cada integración (frontend, ERP, aplicación móvil, banco de pruebas sandbox, etc.), lístalas y revoca las filtradas o sin uso.

GET    /v1/keys
POST   /v1/keys
DELETE /v1/keys/:id
GET    /v1/keys/:id/usage

Autenticación ​

Authorization: Bearer <api-key> — cualquier llave activa del tenant con el scope keys:manage. Cada endpoint de esta página administra llaves en sí mismas, así que una llave más restringida (p. ej. una llave de solo documents:read) no puede listar, crear, revocar ni ver el uso de otras llaves. Tener keys:manage por sí solo tampoco basta para escalar privilegios — ver la regla de contención de privilegios en Crear una nueva llave más abajo. Ver Scopes más abajo.


Scopes ​

Cada llave lleva un arreglo scopes. Una solicitud solo se permite si los scopes de la llave incluyen el scope que exige la ruta de destino — ver Insufficient Scope para el formato del error cuando no lo tiene.

ScopeCubre
documents:writeTodas las mutaciones de comprobantes (POST /v1/documents, /send, /rebuild, /email-retry, etc.) y GET /:accessKey/authorize (dispara una llamada en vivo al SRI y puede enviar un correo, por eso se trata como escritura). También POST /v1/tenants/retry-failed-documents.
documents:readTodos los demás GET bajo /v1/documents (listar, obtener, RIDE, XML, eventos, notas de crédito, respuestas del SRI, estadísticas).
issuers:readTodos los GET bajo /v1/issuers (listar, obtener, tipos de comprobante, secuenciales).
issuers:writeTodos los POST/PATCH/DELETE bajo /v1/issuers (creación de sucursales, actualizaciones, logo, renovación de certificado, tipos de comprobante, secuenciales).
keys:manageToda esta ruta /v1/keys.
billing:manageGET /v1/subscriptions/me, GET /v1/payments/:id/proofs y GET /v1/payments/:id/proofs/:proofId — los únicos tres endpoints de /v1/subscriptions//v1/payments que una llave puede llamar directamente. Cualquier otro endpoint de esas dos rutas (iniciar una suscripción, cambiar de plan/usuarios adicionales, cancelar, enviar o eliminar comprobante, pagos con tarjeta) solo puede llamarlo la propia aplicación web de Comprobify — ver Tu suscripción y cómo pagarla.
webhooks:manage/v1/webhooks completo.
tenant:managePATCH /v1/tenants/language. (También rige la aceptación de los acuerdos legales, que solo se hace desde la aplicación web.)
tenant:promoteLa promoción a producción — separado de tenant:manage porque emite/revoca todas las llaves del tenant y cambia de sandbox a producción de forma irreversible. Esa acción solo se hace desde la aplicación web, así que una llave propia con este scope no puede ejecutarla por sí sola.

La primera llave de un tenant (creada automáticamente en el registro) siempre obtiene las nueve — acceso total, idéntico a cómo se comportaba cualquier llave antes de que existieran los scopes. Crear una llave adicional vía POST /v1/keys es distinto: omitir scopes ahí no da acceso total por defecto — clona los scopes que ya tiene la llave que hace esa llamada (ver Crear una nueva llave más abajo para la regla completa). Sigues pudiendo crear una llave sin enviar scopes en absoluto; solo que obtienes una copia de los scopes de tu propia llave en lugar de acceso total garantizado. Reducir el acceso aún más es opcional: envía un arreglo scopes explícito y más reducido. Las lecturas básicas de identidad (GET /v1/tenants/me, /agreements, /events) y los endpoints de notificaciones/catálogos están exentos de scope — cualquier llave activa puede llamarlos sin importar su arreglo scopes.


Listar llaves ​

GET /v1/keys

Devuelve todas las llaves activas del tenant. El token en texto plano nunca se devuelve — solo etiquetas, ambientes e ids.

Respuesta ​

json
{
  "ok": true,
  "keys": [
    {
      "id": "00000000-0000-0000-0000-000000000017",
      "label": "frontend-prod",
      "environment": "production",
      "scopes": ["documents:write", "documents:read", "issuers:read", "issuers:write", "keys:manage", "billing:manage", "webhooks:manage", "tenant:manage", "tenant:promote"],
      "active": true,
      "createdAt": "2026-03-01T12:00:00.000Z",
      "revokedAt": null,
      "lastUsedAt": "2026-08-07T14:22:10.000Z",
      "requestCount": 15832
    },
    {
      "id": "00000000-0000-0000-0000-000000000018",
      "label": "dashboard-readonly",
      "environment": "production",
      "scopes": ["documents:read"],
      "active": true,
      "createdAt": "2026-04-12T09:30:00.000Z",
      "revokedAt": null,
      "lastUsedAt": null,
      "requestCount": 0
    }
  ],
  "limit": { "max": 5, "used": 2 }
}

lastUsedAt (nullable, null si la llave nunca ha autenticado una solicitud) y requestCount (contador de por vida, no por ventana — para volumen acotado en el tiempo usa los logs estructurados de solicitudes o una herramienta APM) se actualizan en cada solicitud que esa llave autentica con éxito. scopes refleja lo que esa llave tiene permitido hacer actualmente — ver Scopes arriba.

limit.max es cuántas llaves activas puedes tener en total antes de que POST /v1/keys devuelva 402 API_KEY_LIMIT_REACHED, y limit.used es tu conteo actual — coincide exactamente con el máximo de tu plan (ver Planes de suscripción). En Free/Solo/Lite max es 0: esos planes no venden llaves adicionales por self-service, y las llaves internas que la aplicación web usa para operar tu panel nunca cuentan aquí ni aparecen en este listado.

Errores ​

Estado HTTPCódigoCuándo ocurre
401UNAUTHORIZEDAPI key ausente o inválida
403INSUFFICIENT_SCOPELa llave usada en esta solicitud no tiene el scope keys:manage

Crear una nueva llave ​

POST /v1/keys

Crea una nueva llave a nivel de tenant. El token en texto plano se muestra una sola vez en la respuesta y nunca se almacena — regístralo de inmediato.

Cuerpo de la solicitud ​

json
{
  "label": "dashboard-readonly",
  "environment": "sandbox",
  "scopes": ["documents:read"]
}
CampoTipoRequeridoPor defectoDescripción
labelstringNonullNombre legible para la integración (máx. 100 caracteres). Muy recomendado para fines de observabilidad.
environmentstringNo"sandbox""sandbox" o "production". Las llaves de producción solo pueden crearse después de que el tenant haya sido promovido a producción.
scopesstring[]Nouna copia de los scopes de la llave solicitanteArreglo no vacío, cada elemento uno de los 9 valores listados en Scopes arriba. Omitirlo no da acceso total por defecto — clona los scopes que ya tiene la llave que hace esta llamada.

Contención de privilegios: cada elemento de scopes debe estar ya presente en la llave que hace esta solicitud — no puedes crear una llave más amplia que la tuya, ni siquiera si tienes keys:manage. Una llave con acceso total puede crear cualquier combinación (incluyendo otra llave con acceso total); una llave con solo ["keys:manage", "documents:read"] puede crear una llave con ["documents:read"] pero no una con ["documents:write"].

Límite del plan: cada plan limita cuántas llaves activas puede tener un tenant a la vez (ver Planes de suscripción). Revoca una llave sin uso vía DELETE /v1/keys/:id para liberar un cupo, o mejora tu plan.

Respuesta ​

201 Created

json
{
  "ok": true,
  "apiKey": "a3f8c2bd9e10...",
  "scopes": ["documents:read"]
}

El token en texto plano (apiKey) se muestra una sola vez; scopes refleja lo que realmente se otorgó (útil para confirmar que se aplicó el valor por defecto cuando se omitió el campo).

Errores ​

Estado HTTPCódigoCuándo ocurre
400VALIDATION_FAILEDlabel demasiado largo, environment inválido, o scopes está presente pero no es un arreglo no vacío de scopes válidos
401UNAUTHORIZEDAPI key ausente o inválida
403FORBIDDENEl correo del tenant no está verificado, O se intenta crear una llave de producción antes de que algún emisor haya sido promovido
403INSUFFICIENT_SCOPELa llave usada en esta solicitud no tiene el scope keys:manage
403SCOPE_ESCALATION_FORBIDDENscopes incluye un elemento que la llave solicitante no tiene — ver Contención de privilegios arriba
402API_KEY_LIMIT_REACHEDEl tenant ya tiene el número máximo de llaves activas que permite su plan — ver Planes de suscripción

Revocar una llave ​

DELETE /v1/keys/:id

Marca la llave como inactiva. La llave no podrá usarse para autenticar ninguna solicitud futura.

Parámetros de ruta ​

ParámetroDescripción
idUUID de la llave (obtenido de GET /v1/keys)

Respuesta ​

200 OK

json
{ "ok": true }

Errores ​

Estado HTTPCódigoCuándo ocurre
400BAD_REQUESTSe intenta revocar la misma llave que se está usando para hacer esta solicitud — usa una llave diferente, o coordina con soporte de administración
401UNAUTHORIZEDAPI key ausente o inválida
403INSUFFICIENT_SCOPELa llave usada en esta solicitud no tiene el scope keys:manage
404NOT_FOUNDEl id de la llave no existe o ya fue revocado, o pertenece a un tenant diferente

Uso diario de una llave ​

GET /v1/keys/:id/usage

Devuelve una serie diaria de solicitudes autenticadas con esa llave, con exactamente un valor por cada día del rango — los días sin actividad se incluyen con requestCount: 0 en lugar de omitirse, así que no hace falta rellenar huecos antes de graficar la serie.

Parámetros de ruta ​

ParámetroDescripción
idUUID de la llave (obtenido de GET /v1/keys)

Parámetros de consulta ​

ParámetroTipoRequeridoPor defectoDescripción
daysintegerNo30Cuántos días hacia atrás incluir (1–365), contando el día de hoy.
http
GET /v1/keys/00000000-0000-0000-0000-000000000501/usage?days=7
Authorization: Bearer <your-api-key>

Respuesta ​

200 OK

json
{
  "ok": true,
  "usage": [
    { "date": "2026-08-05", "requestCount": 0 },
    { "date": "2026-08-06", "requestCount": 128 },
    { "date": "2026-08-07", "requestCount": 342 }
  ]
}

La serie viene rellenada con ceros — siempre hay exactamente days entradas, una por cada día del rango, aunque la llave no se haya usado ese día. El id puede pertenecer a una llave ya revocada (la propiedad, no el estado active, es lo que da acceso) para poder seguir consultando el historial de una llave revocada.

Errores ​

Estado HTTPCódigoCuándo ocurre
400VALIDATION_FAILEDid no es un UUID válido, o days está fuera del rango 1–365
401UNAUTHORIZEDAPI key ausente o inválida
403INSUFFICIENT_SCOPELa llave usada en esta solicitud no tiene el scope keys:manage
404NOT_FOUNDEl id de la llave no existe o pertenece a un tenant diferente

Ambiente de la llave + emisor de destino ​

Cuando una llave se usa en una solicitud de comprobante, el middleware resolveIssuer valida que el environment de la llave coincida con el ambiente efectivo del emisor de destino. El indicador sandbox reside en el tenant — resolveIssuer lee tenant.sandbox y rechaza cualquier desajuste entre llave y emisor:

Ambiente de la llavesandbox del tenantResultado
sandboxtrueOK
sandboxfalse401 — una llave sandbox no puede dirigirse a un tenant de producción
productiontrue401 — una llave de producción no puede dirigirse a un tenant sandbox
productionfalseOK

Esta es la única salvaguarda que evita solicitudes accidentales entre ambientes; trata el ambiente como parte de la identidad de la llave, no como un detalle aparte de ella.

Documentación de la API de Comprobify — API v1.3.1