Factuarea APIDevelopers

Claves acotadas a una parte de tu cuenta

Emite, acota, rota y revoca API keys que alcanzan solo algunos de los NIF de tu cuenta — scoped_company_ids, el techo de nivel por NIF y qué pasa cuando la persona que emitió una clave pierde acceso.

Una API key pertenece a la cuenta, nunca a uno de sus NIF, y lo que decide qué NIF puede manejar es su ámbito: los scoped_company_ids que declaras al emitirla. Una clave acotada a un solo NIF autentica peticiones que llegan a ese: el segmento {company} de la ruta no puede nombrar ningún otro, y el resto de la cuenta le queda inalcanzable. El ámbito puede contener tus propios NIF y también los que alcanzas por un acceso cedido o por una cuenta gestionada.

Es la alternativa a manejar toda la cuenta con una sola credencial y nombrar el NIF en cada petición: una clave acotada queda fijada a sus NIF al emitirse, en lugar de cambiar en cada petición. Además, cada NIF del ámbito tiene un nivel, view u operate, que nunca puede superar el de la persona que emitió la clave.

Seis endpoints bajo /v1/accounts/{account}/api-keys cubren el ciclo de vida.

OperaciónEndpointScope
Listar clavesGET /v1/accounts/{account}/api-keysaccount:read
Emitir una clavePOST /v1/accounts/{account}/api-keysaccount:write
Consultar una claveGET /v1/accounts/{account}/api-keys/{api_key}account:read
Cambiar los NIF de una clavePATCH /v1/accounts/{account}/api-keys/{api_key}/nif-scopeaccount:write
Rotar el secretoPOST /v1/accounts/{account}/api-keys/{api_key}/rotate-secretaccount:write
Revocar una clavePOST /v1/accounts/{account}/api-keys/{api_key}/revokeaccount:write

Es el mismo autoservicio que describe API keys: esta página trata del ámbito de NIF que das a una clave. Tanto {account} como {api_key} son valores UUID v7 opacos, y lees account.id de GET /v1/me. El sujeto es siempre la cuenta, y quién ve y gestiona una clave explica qué ve una clave de ella.

Emite una clave acotada

POST /v1/accounts/{account}/api-keys emite una clave y devuelve su secret en claro una sola vez. Declara scoped_company_ids con los NIF sobre los que podrá operar la clave. Si lo omites, la clave alcanza los mismos NIF que la clave que la emite, y nunca más. Requiere el scope account:write.

curl -X POST \
  https://api.factuarea.com/v1/accounts/$ACCOUNT_ID/api-keys \
  -H "Authorization: Bearer $FACTUAREA_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "name": "Producción Talleres García",
    "scopes": ["invoices:read", "invoices:write"],
    "scoped_company_ids": ["01931b3e-7c4a-7f2e-9a8b-4d6e7f8a9b0c"]
  }'

Respuesta (201), con una cabecera Location que lleva la URL de la clave nueva:

{
  "data": {
    "object": "api_key",
    "id": "0190f2c0-77aa-7b21-8c33-1d2e3f405162",
    "name": "Producción Talleres García",
    "prefix": "fact_live_1OSf9KdP",
    "scopes": ["invoices:read", "invoices:write"],
    "tier": "scale",
    "environment": "live",
    "created_at": "2026-01-15T09:30:00Z",
    "last_used_at": null,
    "expires_at": null,
    "revoked_at": null,
    "is_active": true,
    "is_revoked": false,
    "secret": "fact_live_1OSf9KdPR2VbY7TcA9eFmN5z"
  }
}

El secret se muestra solo en esta respuesta 201 y tras una rotación, y una repetición idempotente de cualquiera de las dos lo devuelve como null. Ningún endpoint lo devuelve después. Guárdalo en un gestor de secretos en cuanto lo recibas, nunca en un log ni en un repositorio. Si lo pierdes, rota la clave.

CampoObligatorioNotas
namesíEtiqueta legible (1–120 caracteres).
scopessíUno o más scopes del catálogo cerrado v1, cada uno dentro del plan de todos los NIF del ámbito.
scoped_company_idsnoLos NIF (id, UUID v7) que alcanzará la clave, al menos uno cuando está presente. Omitido, la clave alcanza los mismos NIF que la clave que la emite. No se admite con environment: test.
expires_atnoInstante ISO 8601 futuro a partir del cual la clave deja de autenticar.
ip_allowlistnoLista opcional de IP o rangos CIDR permitidos (IPv4, IPv6, /N).
environmentnolive (por defecto) o test para una clave de sandbox.

Tu tramo limita las claves activas. Emitir una por encima del tope de tu tramo responde 422 max_api_keys_exceeded, y cuando la cuenta tiene más de un NIF, toda la cuenta tiene además un tope propio que responde 422 portfolio_max_api_keys_exceeded. El segundo tope es plano dentro de un tramo: dar de alta más NIF nunca lo sube.

El ámbito nunca puede superar al de la clave emisora

Los NIF que pides deben estar dentro del ámbito de la clave que hace la llamada. Pedir uno que no alcanza responde 422 business_rule_violation con el subcódigo nif_scope_exceeds_issuer. No hay recorte silencioso: la clave no se crea alcanzando los NIF que sí caben, falla la petición entera, y el error lista solo los identificadores que enviaste y que la clave no alcanza.

{
  "error": {
    "type": "invalid_request_error",
    "code": "business_rule_violation",
    "subcode": "nif_scope_exceeds_issuer",
    "message": "La credencial nueva no puede alcanzar más NIFs que la credencial que la emite. Fuera del ámbito de la emisora: 01931b3e-8d5b-7a1f-9c2d-5e6f7a8b9c0d.",
    "param": "scoped_company_ids"
  }
}

Un NIF que no se resuelve, o que pertenece a otra cuenta, responde 422 invalid_param_value en el mismo campo scoped_company_ids, y también uno de una cuenta que no te dio acceso: los casos son indistinguibles a propósito, para que el campo no sirva para sondear qué NIF existen. Un NIF de un acceso cedido o de una cuenta gestionada se admite solo mientras la relación esté vigente y tu clave ya lo alcance.

El nivel de cada NIF

Cada NIF del ámbito lleva un nivel, view u operate, que es el techo de lo que la clave puede hacer en él. Se fija cuando el NIF entra en la clave, y es el menor de:

  • el nivel en ese NIF de la persona que emite la clave: un titular o administrador de la cuenta tiene operate en todos los NIF de ella, y un member tiene el nivel de su grant;
  • para un NIF alcanzado por una relación entre cuentas, el nivel de la relación, y el grant interno de la persona cuando es member de la cuenta receptora.

Lo que se deduce:

  • Una clave que escribe solo incluye NIF con operate. Cualquier scope que no sea de lectura (:read), el scope * incluido, necesita operate en cada NIF que la clave nombra, y una clave con solo scopes :read admite view u operate. Nombrar un NIF en el que solo tienes view junto con uno de esos scopes 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 que piden los scopes, y cuando no queda ninguno la respuesta es el mismo 422.
  • Los NIF de una relación quedan bajo su techo. Un NIF cedido o de una cuenta gestionada entra como mucho con el nivel de la relación. Entra solo si la persona que emite la clave pertenece a tu cuenta, y un miembro sin grant en él no lo alcanza. El acceso cedido lo explica desde el lado receptor.
  • El nivel se comprueba en cada petición. El nivel que cuenta es el menor entre el guardado en la clave y el que tiene hoy la persona que la emitió, así que una clave nunca escribe donde su emisora ya no opera.
{
  "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-8d5b-7a1f-9c2d-5e6f7a8b9c0d. Una credencial con permisos de escritura solo alcanza NIF en los que operas.",
    "param": "scoped_company_ids"
  }
}

Cuando la persona que emitió una clave pierde acceso

El nivel guardado de una clave solo baja. Se recalcula a la baja cuando la persona que emitió la clave pierde nivel: se baja o se revoca su grant, su rol pasa de admin a member, se la quita de la cuenta, un NIF sale de la cuenta o se traspasa, o el acceso que alcanza un NIF se reduce o termina. Cada una de estas cosas surte efecto en la siguiente petición:

  • Un NIF que se queda sin nivel sale del ámbito de la clave.
  • Un nivel bajado a view convierte las escrituras de esa clave en ese NIF en 403 company_read_only.
  • Una clave que se queda con el ámbito vacío se revoca.

Nada sube por sí solo. Subir un grant o un rol, o ampliar un acceso, no toca las claves que ya existen: emite una clave nueva, o cambia los NIF de la existente, para obtener el nivel nuevo.

Los scopes se conceden por intersección de los planes

Un scope pedido se concede solo si todos los NIF del ámbito lo habilitan por su plan. Tus propios NIF comparten el plan de tu cuenta, y un NIF alcanzado por una relación aporta el plan de su propia cuenta, así que mezclarlos puede responder 422 scope_not_allowed_by_plan. El exceso nunca se recorta en silencio. 422 scope_not_allowed_in_sandbox cubre un scope que una clave de pruebas no puede llevar. La lista de scopes queda fijada al emitir: ampliarla significa emitir otra clave. El environment y el tier nunca se toman del cuerpo, y el tier se deriva del plan de la cuenta.

Claves de pruebas

Una clave con environment: test alcanza solo la empresa sandbox de tu cuenta, así que declarar scoped_company_ids con ella responde 422 invalid_param_value en ese campo: emítela sin scoped_company_ids. Una credencial fact_test_ no puede emitir claves, cambiar su ámbito, rotarlas ni revocarlas: esas cuatro operaciones responden 403 live_credential_required sin escribir nada, así que una clave de pruebas nunca emite una clave de producción. Para obtener una clave de pruebas, emítela con una clave de producción y environment: test, o créala en la aplicación web. Probar cuentas gestionadas cubre el resto de lo que puede hacer una clave de pruebas.

{
  "error": {
    "type": "authorization_error",
    "code": "live_credential_required",
    "message": "Esta operación modifica la cuenta y exige una clave de producción (fact_live_)",
    "doc_url": "https://docs.factuarea.com/guides/errors#live_credential_required",
    "request_id": "req_01J8Y3M2Q40000000000000009"
  }
}

Cambia los NIF de una clave

PATCH /v1/accounts/{account}/api-keys/{api_key}/nif-scope sustituye los NIF de una clave que ya está desplegada, y no cambia su secreto. scoped_company_ids es la lista resultante completa, no un delta, con al menos un NIF. Úsalo para añadir los NIF de tus clientes a una clave que ya emitiste, o para acotarla. Requiere el scope account:write.

curl -X PATCH \
  https://api.factuarea.com/v1/accounts/$ACCOUNT_ID/api-keys/$API_KEY_ID/nif-scope \
  -H "Authorization: Bearer $FACTUAREA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "scoped_company_ids": [
      "01931b3e-7c4a-7f2e-9a8b-4d6e7f8a9b0c",
      "01931b3e-8d5b-7a1f-9c2d-5e6f7a8b9c0d"
    ]
  }'

Respuesta (200), el ámbito con el que queda la clave:

{
  "data": {
    "id": "0190f2c0-77aa-7b21-8c33-1d2e3f405162",
    "object": "api_key_nif_scope",
    "scope": [
      {
        "id": "01931b3e-7c4a-7f2e-9a8b-4d6e7f8a9b0c",
        "tax_id": "B12345674",
        "name": "Talleres García SL"
      },
      {
        "id": "01931b3e-8d5b-7a1f-9c2d-5e6f7a8b9c0d",
        "tax_id": "B87654323",
        "name": "Distribuciones Norte SL"
      }
    ]
  }
}

Se aplican los mismos techos que al emitir una clave:

  • Tu propio alcance. Solo puedes cambiar una clave cuyo ámbito actual está dentro del tuyo, y el ámbito nuevo nunca puede superar al tuyo: nif_scope_exceeds_issuer en caso contrario. Cada NIF debe estar en tu cuenta o alcanzarse por una relación vigente, y en el entorno de la clave.
  • Niveles. Un NIF que entra toma el nivel que tiene ahora la persona que emitió la clave, y se rechaza con nif_access_level_exceeds_emitter si esa persona no lo alcanza con el nivel que necesita la clave. Los NIF que siguen conservan su nivel guardado: cambiar el ámbito nunca sube uno.
  • Planes. Cada scope que la clave ya tiene se comprueba de nuevo contra el plan de todos los NIF del ámbito nuevo. Un scope que uno de ellos no permite responde 422 scope_not_allowed_by_plan y no cambia nada.
  • Lo que no se puede cambiar. Una clave publicada en un navegador, porque tiene orígenes permitidos, mantiene su ámbito congelado y responde 422 resource_immutable. Una clave revocada responde 422 api_key_already_revoked, y una clave de pruebas no puede cambiar su ámbito. Enviar de nuevo el mismo ámbito no cambia nada.

Quién ve y gestiona una clave

Una clave lista, consulta, rota, revoca y cambia el ámbito de otra clave de su cuenta solo si todo el ámbito de esa otra está contenido en el suyo. Cualquier otra cosa responde 404 api_key_not_found, igual que una clave que no existe o que pertenece a otra cuenta. Es contención y no intersección porque gestionar una clave da su secreto, y el secreto da todo su ámbito: una clave acotada a {A} podría, de otro modo, rotar una acotada a {A, B} y alcanzar B.

Así, una clave acotada a un NIF no puede ver las claves de sus hermanas, y una clave ve toda clave cuyos NIF ella también alcanza. El listado incluye las claves revocadas, para que conserves el historial, y nunca devuelve un secreto. La contención cuenta los NIF que una clave alcanza hoy: los que dejó atrás un acceso que terminó no cuentan.

Rota el secreto

POST /v1/accounts/{account}/api-keys/{api_key}/rotate-secret genera un prefix y un secret nuevos y devuelve el secreto nuevo en claro una sola vez. El secreto anterior sigue funcionando durante una ventana de gracia de 24 horas, para que puedas desplegar el nuevo sin cortes. Exige una Idempotency-Key y el scope account:write.

curl -X POST \
  https://api.factuarea.com/v1/accounts/$ACCOUNT_ID/api-keys/$API_KEY_ID/rotate-secret \
  -H "Authorization: Bearer $FACTUAREA_KEY" \
  -H "Idempotency-Key: $(uuidgen)"

Durante la ventana de gracia autentican los dos secretos. Cuando caduca, el anterior se rechaza, y una segunda rotación dentro de la ventana conserva solo el secreto que era el vigente antes de ella y descarta el más antiguo al instante. Despliega el secreto nuevo dentro de esas 24 horas. La rotación es irreversible: API keys describe el aviso que lleva una petición con el secreto anterior.

Revoca una clave

POST /v1/accounts/{account}/api-keys/{api_key}/revoke revoca una clave de forma permanente. Las peticiones posteriores autenticadas con ella fallan con 401. Un reason opcional, de hasta 500 caracteres, queda en el registro de auditoría. Exige una Idempotency-Key y el scope account:write. Puedes revocar la clave que estás usando, y al hacerlo te cortas tu propio acceso.

curl -X POST \
  https://api.factuarea.com/v1/accounts/$ACCOUNT_ID/api-keys/$API_KEY_ID/revoke \
  -H "Authorization: Bearer $FACTUAREA_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ "reason": "Rotated out of the deploy pipeline" }'

La revocación es irreversible. Una vez revocada, la clave no se puede restaurar: emite una nueva si la integración aún necesita acceso a la API.

Scopes y aislamiento

La gestión de claves se controla con los scopes de cuenta:

  • account:read lista y consulta las claves de tu cuenta que ves.
  • account:write las emite, cambia su ámbito, las rota y las revoca.

Toda operación está limitada a tu cuenta. Un {account} que no es tuyo responde 404 account_not_found, nunca un 403, y es indistinguible de una cuenta que no existe. El mismo aislamiento rige la cartera de NIF y nombrar un NIF en la ruta: una clave solo puede ver y actuar sobre los NIF de su ámbito.

Permisos de tiendas

La gestión de tiendas usa stores:read y stores:write ; los scopes del proveedor son woocommerce_store:read , woocommerce_store:write , shopify_store:read y shopify_store:write . Las pruebas 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 tabla de operaciones de tiendas.

En esta página

¿Te echamos una mano?Contactar con soporte