Factuarea APIDevelopers

API keys (autoservicio)

Emite, lista, acota, rota y revoca las API keys de tu cuenta desde la API v1 — quién puede emitirlas, los environments live/test, los scopes que puedes asignar y el techo de nivel por NIF.

Más allá del dashboard de desarrollador, Factuarea expone todo el ciclo de vida de las API keys de tu cuenta desde la API pública v1, para que aprovisiones y rotes credenciales de forma programática. Una API key pertenece a la cuenta, nunca a uno de sus NIF, así que vive en el eje de cuenta: seis endpoints bajo /v1/accounts/{account}/api-keys cubren listar, crear, recuperar, acotar, rotar el secret y revocar.

OperaciónEndpointScope
Listar keysGET /v1/accounts/{account}/api-keysaccount:read
Crear una keyPOST /v1/accounts/{account}/api-keysaccount:write
Recuperar una keyGET /v1/accounts/{account}/api-keys/{api_key}account:read
Cambiar los NIF de una keyPATCH /v1/accounts/{account}/api-keys/{api_key}/nif-scopeaccount:write
Rotar el secretPOST /v1/accounts/{account}/api-keys/{api_key}/rotate-secretaccount:write
Revocar una keyPOST /v1/accounts/{account}/api-keys/{api_key}/revokeaccount:write

{account} es el id opaco de la cuenta a la que pertenece la credencial —lo lees en account.id de GET /v1/me—. Tiene que ser tu propia cuenta: cualquier otro valor responde el mismo 404 account_not_found. {api_key} es el id de la key — un UUID v7 opaco, no su prefijo ni su secret. Consulta los esquemas completos en la Referencia de la API.

Quién puede emitir una key

Una key la emite siempre una persona, y lo que alcanza se mide contra esa persona. Las keys se emiten en dos sitios:

DóndeQuién puedeQué recibe la key nueva
La aplicación web, en Ajustes → Desarrolladores → API KeysUn titular o administrador de la cuenta dueña del NIF que tienes seleccionado. Un miembro, un asesor externo (siempre es miembro) y una persona que alcanza el NIF solo por un acceso cedido no pueden: la aplicación web pide un administrador de la cuenta.Los NIF que le asignes, cada uno con el nivel que te da tu rol.
POST /v1/accounts/{account}/api-keysCualquier key de tu cuenta que lleve account:write.NIF dentro del ámbito de la key que la emite, y nunca más.
  • El nivel sale de la persona. Un owner y un admin alcanzan todos los NIF de la cuenta con operate. Un member alcanza solo los NIF en los que tiene un grant, con el nivel de ese grant (roles). Una key toma en cada NIF el nivel de la persona que la emitió, y solo baja.
  • Una key emitida por la API responde ante dos límites. Su ámbito no puede superar el de la key que la emite, y sus niveles no pueden superar lo que tiene hoy la persona que hay detrás de esa key.
  • accounts:read y accounts:write exigen más. Son scopes privilegiados: quien emite debe ser titular o administrador, y la cuenta debe tener un privilegio que solo concede Factuarea.

Lista tus keys

GET /v1/accounts/{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. Las keys revocadas siguen en la lista, para que veas el historial.

curl https://api.factuarea.com/v1/accounts/{account}/api-keys \
  -H "Authorization: Bearer fact_live_8KqW3pXnR2VbY7TcA9eFmN5z"
{
  "data": [
    {
      "id": "0190f2b1-1c4e-7a3d-9f10-0a1b2c3d4e5f",
      "object": "api_key",
      "name": "Production sync",
      "prefix": "fact_live_8KqW3pXn",
      "scopes": ["invoices:read", "invoices:write"],
      "tier": "scale",
      "environment": "live",
      "created_at": "2026-06-01T09:30:00Z",
      "last_used_at": "2026-06-23T18:04:11Z",
      "expires_at": null,
      "revoked_at": null,
      "is_active": true,
      "is_revoked": false
    }
  ],
  "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.

El listado, la recuperación, la rotación, la revocación y el cambio de ámbito trabajan sobre las keys cuyo ámbito entero cabe dentro del ámbito de la key con la que te autenticas. Una key que alcanza un NIF que la tuya no alcanza no aparece en tu listado, y pedirla responde 404 api_key_not_found.

Crea una key

POST /v1/accounts/{account}/api-keys emite una key nueva y devuelve su secret en claro 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/accounts/{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"],
    "scoped_company_ids": [
      "0193f1a0-5c2e-7b41-8d06-9a1e2f3c4d5e",
      "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a01"
    ]
  }'

Respuesta (201, con una cabecera Location que apunta a la key nueva):

{
  "data": {
    "id": "0190f2c0-77aa-7b21-8c33-1d2e3f405162",
    "object": "api_key",
    "name": "Reporting export",
    "prefix": "fact_live_1N0Fnyhh",
    "scopes": ["invoices:read", "pdfs:read"],
    "tier": "scale",
    "environment": "live",
    "created_at": "2026-06-24T08:15:00Z",
    "last_used_at": null,
    "expires_at": null,
    "revoked_at": null,
    "is_active": true,
    "is_revoked": false,
    "secret": "fact_live_1N0FnyhhR2VbY7TcA9eFmN5z"
  }
}

El campo secret aparece solo en esta respuesta 201 (y tras una rotación). No lo devuelve nunca el listado, la recuperación ni ningún otro endpoint. Si lo pierdes debes rotar la key. Persístelo en un gestor de secrets de inmediato — nunca en un log ni en un repositorio.

Envía una Idempotency-Key para que un reintento tras un fallo de red no cree una segunda key. La repetición responde el mismo 201 con secret a null, porque nunca guardamos el secret: si no recibiste la primera respuesta, revoca esa key y crea una nueva.

Cuerpo de la petición

CampoObligatorioNotas
namesíEtiqueta legible (1–120 caracteres).
scopessíUno o más scopes del catálogo cerrado. Mínimo uno. Consulta los scopes que puedes asignar.
environmentnolive (por defecto) o test. Consulta más abajo.
scoped_company_idsnoLos NIF a los que llega la key, por id (UUID v7). Si lo omites, la key llega a los mismos NIF que la key que la crea, y nunca a más. No se admite con environment: test. Consulta los NIF a los que llega una key.
expires_atnoInstante ISO 8601 futuro a partir del cual la key deja de autenticar.
ip_allowlistnoLista opcional de IPs / rangos CIDR permitidos (IPv4, IPv6, /N). Una petición desde otra dirección responde 401 ip_not_allowed.

El tier se deriva del plan de tu cuenta — no se puede fijar desde el cuerpo y no existe una compra de capacidad independiente. Si envías tier, se ignora.

Al crear una key se aplican dos topes, los dos por tier y los dos contados sobre keys activas. max_api_keys_exceeded (422) dice que la empresa que guarda la key ya tiene las keys que permite su plan. portfolio_max_api_keys_exceeded (422) se aplica cuando tu cuenta tiene dos o más NIF reales y se cuenta sobre todas las keys activas de la cuenta, no por NIF, así que dar de alta un NIF no lo sube. Revocar una key libera su plaza. Límites de peticiones describe los límites de una cartera.

El campo environment

Cada key pertenece a uno de los dos environments, fijado al crearla y visible en el objeto de la key:

environmentPrefijoOpera sobre
livefact_live_Tus NIF reales, con efectos reales (VeriFactu → AEAT, emails, webhooks).
testfact_test_La empresa sandbox de tu cuenta, aislada y con los efectos externos desactivados.

Pasa environment: test al crear una key para emitir una credencial de sandbox; omítelo para una key live. El prefijo refleja el environment, así que los distingues sin decodificar la key. Consulta Modo de prueba y sandbox para saber qué se desactiva en test.

curl -X POST https://api.factuarea.com/v1/accounts/{account}/api-keys \
  -H "Authorization: Bearer fact_live_8KqW3pXnR2VbY7TcA9eFmN5z" \
  -H "Content-Type: application/json" \
  -d '{"name": "Integration tests", "scopes": ["invoices:read", "invoices:write"], "environment": "test"}'

Una key fact_test_ pertenece a tu cuenta real — su empresa sandbox vive dentro de ella — y eso decide lo que puede hacer con las keys:

  • Alcanza solo su sandbox. Declarar scoped_company_ids junto con environment: test falla la validación, porque una key de pruebas no tiene ningún otro NIF al que llegar. Una key live tampoco puede llevar la sandbox: mezclarlos responde 422 business_rule_violation con el subcódigo nif_scope_environment_mismatch.
  • Lee la cuenta como una key live. Listar y recuperar keys con una key de pruebas responde igual que con una live.
  • Nunca escribe. Crear, rotar, revocar o cambiar el ámbito de una key con una key de pruebas responde 403 live_credential_required y no cambia nada. Eso incluye pedir una key live, y también pedir otra key de pruebas: emite las keys de pruebas con una key live o en la aplicación web.

Probar cuentas gestionadas explica en qué cuentas puede escribir una key de pruebas.

Los NIF a los que llega una key

El ámbito de una key es la lista de NIF a los que llega, y GET /v1/me lo enumera en scope. Se fija al crear la key, y puedes cambiarlo después.

  • Sin scoped_company_ids la key llega a los mismos NIF que la key que la crea, nunca a más. Se dejan fuera los NIF en los que la persona que emite no alcanza el nivel que piden tus scopes.
  • Con scoped_company_ids la key llega exactamente a esos NIF, y tienen que caber en el ámbito de la key emisora: nombrar uno fuera responde 422 business_rule_violation con el subcódigo nif_scope_exceeds_issuer y enumera los NIF que no caben, sin crear nada. El ámbito nunca se recorta en silencio.
  • Qué NIF se pueden nombrar. Los de tu cuenta, y los que tu cuenta alcanza por una relación vigente: un acceso cedido o una cuenta gestionada. Cualquier otro, y cualquier identificador que no exista, responde el mismo 422 invalid_param_value con param scoped_company_ids, para que la respuesta no sirva para censar NIF.

PATCH /v1/accounts/{account}/api-keys/{api_key}/nif-scope sustituye el ámbito de una key que ya desplegaste. scoped_company_ids es la lista resultante completa, no un delta, con al menos un NIF:

curl -X PATCH \
  https://api.factuarea.com/v1/accounts/{account}/api-keys/0190f2b1-1c4e-7a3d-9f10-0a1b2c3d4e5f/nif-scope \
  -H "Authorization: Bearer fact_live_8KqW3pXnR2VbY7TcA9eFmN5z" \
  -H "Content-Type: application/json" \
  -d '{"scoped_company_ids": ["0193f1a0-5c2e-7b41-8d06-9a1e2f3c4d5e", "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a01"]}'
{
  "data": {
    "id": "0190f2b1-1c4e-7a3d-9f10-0a1b2c3d4e5f",
    "object": "api_key_nif_scope",
    "scope": [
      { "id": "0193f1a0-5c2e-7b41-8d06-9a1e2f3c4d5e", "tax_id": "B12345674", "name": "Distribuciones Ejemplo SL" },
      { "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a01", "tax_id": "B87654323", "name": "Talleres García SL" }
    ]
  }
}
  • Solo dentro de tu ámbito. Solo puedes cambiar una key cuyo ámbito actual cabe dentro del tuyo, y el ámbito nuevo nunca puede superar el tuyo.
  • Los scopes de la key se comprueban de nuevo. Cada scope que lleva la key tiene que estar permitido por el plan de todos los NIF de la lista nueva. Si no, la respuesta es 422 scope_not_allowed_by_plan y no cambia nada.
  • Niveles. Un NIF que se queda conserva el nivel guardado en la key, así que cambiar el ámbito nunca lo sube. Un NIF que entra toma el nivel de la persona que emitió la key.
  • Mismas respuestas que al crear. Se aplican los mismos errores 422, y una key revocada responde 422 api_key_already_revoked. Una key de pruebas tiene un ámbito fijo, su sandbox: cualquier otra lista responde nif_scope_environment_mismatch.

Claves acotadas explica cómo usar una key que llega solo a una parte de la cuenta.

El techo de nivel por NIF

Cada NIF de una key tiene un nivel, view u operate. Se fija cuando el NIF entra en la key, al emitirla o al cambiar su ámbito, y solo baja. Es el menor de tres: el nivel de la relación, cuando el NIF es de otra cuenta a la que llegas por un acceso cedido o una cuenta gestionada; el grant de la persona que emite la key; y el rol de esa persona.

  • Escribir exige operate. Una key con cualquier scope que no sea de lectura (:read), incluido *, necesita operate en cada NIF que nombra. A una key que solo lleva scopes :read le basta con view.
  • Un NIF que la persona que emite solo lee. Nombrarlo junto con un scope de escritura responde 422 business_rule_violation con el subcódigo nif_access_level_exceeds_emitter y no crea nada. Si no declaras scoped_company_ids, se dejan fuera los NIF por debajo del nivel necesario, y cuando no queda ninguno la respuesta es el mismo 422.
  • Se mide de nuevo en cada petición. Cuenta el menor entre el nivel guardado en la key y el nivel que la persona que emite tiene en ese momento. Con view, una escritura responde 403 company_read_only, y sin ningún nivel, el mismo 404 profile_not_found que un NIF fuera del ámbito.
  • Se recalcula a la baja. Bajar o retirar un grant baja las keys de esa persona, y reducir o terminar un acceso entre cuentas baja las keys de la cuenta receptora en la siguiente petición. Una key que se queda sin ningún NIF se revoca. Nada sube por sí solo: para obtener un nivel más alto, emite una key nueva.
{
  "error": {
    "type": "invalid_request_error",
    "code": "business_rule_violation",
    "subcode": "nif_access_level_exceeds_emitter",
    "message": "No puedes dar a la credencial más acceso del que tienes. Sin acceso suficiente en: 01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a01. Una credencial con permisos de escritura solo alcanza NIF en los que operas.",
    "param": "scoped_company_ids",
    "doc_url": "https://docs.factuarea.com/guides/errors#business_rule_violation",
    "request_id": "req_01J8Y3M2Q40000000000000011"
  }
}

Acceso cedido muestra el techo de una key en un NIF que otra cuenta te deja alcanzar, y qué pasa con las keys cuando ese acceso se reduce o termina.

Los scopes que puedes asignar

scopes toma valores del catálogo cerrado de Autenticación. Un valor fuera de él falla la validación con 422 invalid_param_value.

  • El plan decide, NIF a NIF. Un scope se concede solo si el plan de todos los NIF del ámbito lo permite, y el exceso nunca se recorta en silencio: responde 422 scope_not_allowed_by_plan. Un módulo bloqueado en modo de prueba responde 422 scope_not_allowed_in_sandbox. Los scopes members:*, invitations:* y nif_transfers:* necesitan el módulo user_management.
  • accounts:read y accounts:write no te los puedes asignar tú. Son scopes privilegiados: una key los lleva solo mientras la cuenta tenga un privilegio que solo concede Factuarea, y solo si la persona que emite la key es titular o administrador. Si no, la creación responde 403 privileged_scope_required y no se crea ninguna key.
  • * no los cubre. El super-scope cubre todos los demás scopes. Con el privilegio puedes listar * y accounts:* juntos en la misma key.

Cuentas gestionadas explica qué abre el privilegio.

Rota el secret

POST /v1/accounts/{account}/api-keys/{api_key}/rotate-secret genera un prefix + secret nuevos y devuelve el secret nuevo en claro exactamente una vez. El secret anterior sigue funcionando durante una ventana de gracia de 24 horas para que puedas desplegar el nuevo sin tiempo de inactividad. El environment de la key no cambia.

Es irreversible, así que la Idempotency-Key es obligatoria: sin ella la respuesta es 422 idempotency_key_required.

curl -X POST \
  https://api.factuarea.com/v1/accounts/{account}/api-keys/0190f2b1-1c4e-7a3d-9f10-0a1b2c3d4e5f/rotate-secret \
  -H "Authorization: Bearer fact_live_8KqW3pXnR2VbY7TcA9eFmN5z" \
  -H "Idempotency-Key: $(uuidgen)"
{
  "data": {
    "id": "0190f2b1-1c4e-7a3d-9f10-0a1b2c3d4e5f",
    "object": "api_key",
    "name": "Production sync",
    "prefix": "fact_live_Zq7mP4xV",
    "scopes": ["invoices:read", "invoices:write"],
    "tier": "scale",
    "environment": "live",
    "created_at": "2026-06-01T09:30:00Z",
    "last_used_at": "2026-06-23T18:04:11Z",
    "expires_at": null,
    "revoked_at": null,
    "is_active": true,
    "is_revoked": false,
    "secret": "fact_live_Zq7mP4xVnR2VbY7TcA9eFmN5z"
  }
}

Durante la ventana de gracia de 24 horas autentican tanto el secret nuevo como el anterior; una petición que siga usando el anterior recibe una cabecera 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/accounts/{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. Igual que la rotación, es irreversible y exige una Idempotency-Key.

curl -X POST \
  https://api.factuarea.com/v1/accounts/{account}/api-keys/0190f2b1-1c4e-7a3d-9f10-0a1b2c3d4e5f/revoke \
  -H "Authorization: Bearer fact_live_8KqW3pXnR2VbY7TcA9eFmN5z" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -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 autenticas la petición, cortando tu propio acceso. Asegúrate de tener antes otra key válida si aún necesitas acceso a la API.

Tras la revocación, las peticiones con esa key devuelven 401 con el código api_key_revoked:

{
  "error": {
    "type": "authentication_error",
    "code": "api_key_revoked",
    "message": "Esta API key ha sido revocada.",
    "doc_url": "https://docs.factuarea.com/guides/errors#api_key_revoked",
    "request_id": "req_01JBVH7K9Y4N3CDQ2EHJB1AGSV"
  }
}

El código es específico porque el secret todavía coincide: quien lo envía ya tiene la key. Un secret que no coincide con nada responde el genérico invalid_api_key, y una key caducada responde api_key_expired.

Scopes y aislamiento

Los seis endpoints están protegidos por los scopes de account:

  • account:read — listar y recuperar keys.
  • account:write — crear, cambiar el ámbito de, rotar y revocar keys.

Todas las operaciones se acotan a tu propia cuenta y, dentro de ella, al ámbito de la key con la que te autenticas. Las respuestas nunca revelan lo que existe, y ninguna es un 403:

  • Un {account} que no es tuyo, no existe o no es un identificador de cuenta responde 404 account_not_found.
  • El id de una key que pertenece a otra cuenta, no existe o llega a un NIF fuera de tu ámbito responde 404 api_key_not_found.

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), como titular o administrador de la cuenta, y después usa estos endpoints para aprovisionar el resto de forma programática. Consulta Autenticación para el formato de la key y las cabeceras.

Errores

CódigoHTTPCuándo
insufficient_scope403La key no lleva ni el scope de la operación ni *.
live_credential_required403Una key fact_test_ intenta crear, rotar, revocar o cambiar el ámbito de una key.
privileged_scope_required403Pides accounts:read o accounts:write y la cuenta no tiene el privilegio, o quien emite ya no es titular ni administrador.
account_not_found404{account} no es tu cuenta.
api_key_not_found404La key no existe, pertenece a otra cuenta o llega a un NIF fuera de tu ámbito.
invalid_param_value422Un scope está fuera del catálogo, o scoped_company_ids nombra un NIF que no existe o que tu cuenta no alcanza.
business_rule_violation422Subcódigos nif_scope_exceeds_issuer, nif_access_level_exceeds_emitter, nif_scope_environment_mismatch y issuer_company_outside_account.
scope_not_allowed_by_plan422Un scope pedido no lo permite el plan de algún NIF del ámbito.
scope_not_allowed_in_sandbox422Una key de pruebas pide un scope de un módulo bloqueado en modo de prueba.
max_api_keys_exceeded422La empresa que guarda la key ha alcanzado las keys que permite su plan.
portfolio_max_api_keys_exceeded422La cuenta ha alcanzado las keys activas que permite una cartera.
api_key_already_revoked422Intentas rotar, revocar o cambiar el ámbito de una key que ya está revocada.
idempotency_key_required422Rotas o revocas sin Idempotency-Key.

Tools MCP

Las mismas operaciones son tools MCP: list_api_keys, get_api_key, create_api_key, rotate_api_key_secret, revoke_api_key y update_api_key_nif_scope. Las dos lecturas también se pueden usar por OAuth. Las cuatro escrituras necesitan una API key, porque el consentimiento OAuth nunca concede account:write. Consulta Scopes de MCP.

Permisos de tiendas

La gestión de tiendas usa stores:read y stores:write; los scopes propios de cada proveedor son woocommerce_store:read, woocommerce_store:write, shopify_store:read y shopify_store:write. Las operaciones de prueba de conexión requieren el scope de escritura del proveedor. Estos scopes se asignan a API keys y quedan fuera del consentimiento OAuth. Consulta la matriz de operaciones en tiendas ecommerce.

En esta página

¿Te echamos una mano?Contactar con soporte