API keys (autoservicio)
Lista, crea, rota y revoca tus API keys desde la API v1 — el secret se muestra una vez, los environments son live/test y el tier lo deriva tu plan.
Más allá del dashboard de desarrollador, Factuarea expone todo el ciclo de
vida de tus API keys desde la API pública v1, para que aprovisiones y rotes
credenciales de forma programática. Cinco endpoints bajo
/v1/account/api-keys cubren listar, crear, recuperar, rotar el secret y
revocar — todos limitados a la empresa autenticada.
| Operación | Endpoint | Scope |
|---|---|---|
| Listar keys | GET /v1/account/api-keys | account:read |
| Crear una key | POST /v1/account/api-keys | account:write |
| Recuperar una key | GET /v1/account/api-keys/{api_key} | account:read |
| Rotar el secret | POST /v1/account/api-keys/{api_key}/rotate_secret | account:write |
| Revocar una key | POST /v1/account/api-keys/{api_key}/revoke | account:write |
{api_key} es el id de la key — un UUID v7 opaco, no su prefix ni su
secret. Mira los esquemas completos en la
Referencia de la API.
Lista tus keys
GET /v1/account/api-keys devuelve tus keys con paginación por
cursor. Cada key expone su prefix, scopes, tier,
environment y los timestamps de su ciclo de vida — nunca el secret.
curl https://api.factuarea.com/v1/account/api-keys \
-H "Authorization: Bearer fact_live_8KqW3pXnR2VbY7TcA9eFmN5z"{
"data": [
{
"object": "api_key",
"id": "0190f2b1-1c4e-7a3d-9f10-0a1b2c3d4e5f",
"name": "Production sync",
"prefix": "fact_live_8KqW3pXn",
"scopes": ["invoices:read", "invoices:write"],
"tier": "scale",
"environment": "live",
"active": true,
"revoked": false,
"last_used_at": "2026-06-23T18:04:11Z",
"expires_at": null,
"revoked_at": null
}
],
"has_more": false,
"next_cursor": null
}prefix son los primeros caracteres de la key — seguro de registrar en
logs, no autentica. Úsalo para reconocer una key en tus propios paneles
sin guardar nunca el secret.
Crea una key
POST /v1/account/api-keys emite una nueva key y devuelve su secret en
texto plano exactamente una vez. Guárdalo en el momento en que lo
recibes — no hay ningún endpoint para volver a leerlo más tarde.
curl -X POST https://api.factuarea.com/v1/account/api-keys \
-H "Authorization: Bearer fact_live_8KqW3pXnR2VbY7TcA9eFmN5z" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"name": "Reporting export",
"scopes": ["invoices:read", "pdfs:read"],
"environment": "test"
}'Respuesta (201):
{
"data": {
"object": "api_key",
"id": "0190f2c0-77aa-7b21-8c33-1d2e3f405162",
"name": "Reporting export",
"prefix": "fact_test_1N0Fnyhh",
"secret": "fact_test_1N0FnyhhR2VbY7TcA9eFmN5z",
"scopes": ["invoices:read", "pdfs:read"],
"tier": "scale",
"environment": "test"
}
}El campo secret aparece solo en esta respuesta 201 (y tras una
rotación). Nunca lo devuelve el listado, la recuperación ni ningún otro
endpoint. Si lo pierdes tienes que rotar la key. Persístelo en un gestor
de secretos de inmediato — nunca en un log ni en un repositorio.
Cuerpo de la petición
| Campo | Obligatorio | Notas |
|---|---|---|
name | sí | Etiqueta legible (1–120 caracteres). |
scopes | sí | Uno o más scopes del catálogo cerrado. Mínimo uno. |
environment | no | live (por defecto) o test. Ver abajo. |
expires_at | no | Instante futuro ISO 8601 a partir del cual la key deja de autenticar. |
allowed_ips | no | Lista opcional de IPs / CIDR permitidas (IPv4, IPv6, /N). |
El tier se deriva del plan de tu empresa (o de un
boost de capacidad activo cuando es
superior) — no se fija desde el cuerpo. Si envías un tier, se ignora. Pedir un scope fuera del
catálogo cerrado, o un scope por encima de tu plan, devuelve 422 con
errores por campo.
El campo environment
Cada key pertenece a uno de los dos environments, fijado al crearla y visible en el objeto de la key:
environment | Prefix | Opera sobre |
|---|---|---|
live | fact_live_ | Tu empresa real, con efectos reales (VeriFactu → AEAT, emails, webhooks). |
test | fact_test_ | Una empresa sandbox aislada con los efectos externos desactivados. |
Pasa environment: test al crear una key para emitir una credencial de
sandbox; omítelo para una key de producción. El prefix refleja el
environment, así que los distingues sin decodificar la key. Mira Modo de
prueba y sandbox para saber qué se desactiva en test.
Rota el secret
POST /v1/account/api-keys/{api_key}/rotate_secret genera un nuevo
prefix + secret y devuelve el nuevo secret en texto plano
exactamente una vez. El secret anterior sigue funcionando durante
una ventana de gracia de 24 horas para que puedas desplegar el nuevo
sin downtime.
curl -X POST \
https://api.factuarea.com/v1/account/api-keys/0190f2b1-1c4e-7a3d-9f10-0a1b2c3d4e5f/rotate_secret \
-H "Authorization: Bearer fact_live_8KqW3pXnR2VbY7TcA9eFmN5z"{
"data": {
"object": "api_key",
"id": "0190f2b1-1c4e-7a3d-9f10-0a1b2c3d4e5f",
"prefix": "fact_live_Zq7mP4xV",
"secret": "fact_live_Zq7mP4xVnR2VbY7TcA9eFmN5z",
"scopes": ["invoices:read", "invoices:write"],
"environment": "live"
}
}Durante la ventana de gracia de 24 horas autentican tanto el nuevo como
el secret anterior; una petición que siga usando el anterior recibe un
header 199 Warning con la cuenta atrás de horas restantes. Al
expirar la ventana el secret anterior se rechaza y se purga. Despliega
el nuevo secret dentro de esas 24 horas. La rotación es irreversible.
Revoca una key
POST /v1/account/api-keys/{api_key}/revoke invalida una key de forma
permanente. Las peticiones posteriores autenticadas con ella fallan con
401. Un reason opcional (máx 500 caracteres) queda en el audit log.
curl -X POST \
https://api.factuarea.com/v1/account/api-keys/0190f2b1-1c4e-7a3d-9f10-0a1b2c3d4e5f/revoke \
-H "Authorization: Bearer fact_live_8KqW3pXnR2VbY7TcA9eFmN5z" \
-H "Content-Type: application/json" \
-d '{"reason": "Rotated out of the deploy pipeline"}'La revocación es irreversible y no se limita a otras keys: puedes revocar la propia key con la que estás autenticando la petición, cortando tu propio acceso. Asegúrate de tener otra key válida en su sitio antes si todavía necesitas acceso a la API.
Tras la revocación, las peticiones con esa key devuelven 401 con el código
genérico invalid_api_key — no un código específico de "revocada":
{
"error": {
"type": "authentication_error",
"code": "invalid_api_key",
"message": "La API key proporcionada no es válida.",
"request_id": "req_01JBVH7K9Y4N3CDQ2EHJB1AGSV"
}
}Esto es anti-enumeración deliberada: la API nunca revela si una key fue
revocada, ha caducado o nunca existió — toda key inutilizable se ve igual
para un atacante. Ramifica tu propia lógica según el resultado 200/401,
no según un código específico de revocada.
Scopes y aislamiento
Los cinco endpoints están protegidos por los scopes de account:
account:read— listar y recuperar keys.account:write— crear, rotar y revocar keys.
Todas las operaciones están limitadas a la empresa autenticada. Un id de
key que pertenece a otra empresa devuelve 404 api_key_not_found (de nuevo,
anti-enumeración — nunca revela que la key existe), nunca 403.
Gestionar keys sigue requiriendo una key existente con los scopes adecuados. Crea tu primera key en el dashboard de desarrollador (app.factuarea.com/settings/developers/api-keys), y luego usa estos endpoints para aprovisionar el resto de forma programática. Mira Autenticación para el formato de la key y las cabeceras.