Factuarea API

Child company API keys

Mint, rotate and revoke API keys scoped to a single child company, deriving their scopes from the calling key — the api_keys endpoints under a managed company.

Each managed company has its own set of API keys. A child key authenticates requests on behalf of that one company — it never reaches sibling companies or the master tenant. It is the alternative to driving a child with the X-Active-Profile header: a child key is bound to one company for good, rather than switched per request.

Five endpoints under /v1/companies/{id}/api-keys cover the lifecycle.

OperationEndpointScope
List child keysGET /v1/companies/{id}/api-keysapi_keys:read
Create a child keyPOST /v1/companies/{id}/api-keysapi_keys:write
Retrieve a child keyGET /v1/companies/{id}/api-keys/{key}api_keys:read
Rotate the secretPOST /v1/companies/{id}/api-keys/{key}/rotate-secretapi_keys:write
Revoke a child keyDELETE /v1/companies/{id}/api-keys/{key}api_keys:write

This mirrors the account-level API keys self-service, scoped to a child company instead of your own account. Both {id} (the company) and {key} (the API key) are opaque UUID v7 values.

Create a child key

POST /v1/companies/{id}/api-keys mints a key for the company and returns its plaintext secret exactly once. Requires the api_keys:write scope.

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

Response (201):

{
  "data": {
    "object": "api_key",
    "id": "0190f2c0-77aa-7b21-8c33-1d2e3f405162",
    "name": "Producción Talleres García",
    "prefix": "fact_live_1OSf9KdP",
    "secret": "fact_live_1OSf9KdPR2VbY7TcA9eFmN5z",
    "scopes": ["invoices:read", "invoices:write"],
    "tier": "scale",
    "environment": "live"
  }
}

The secret is shown only in this 201 response and after a rotation. No endpoint returns it later. Persist it to a secret manager the moment you receive it — never to a log or a repository. If you lose it, rotate the key.

Scopes must be a subset of the parent key

The scopes you request for a child key must be a subset of the scopes of the key making the call. Requesting a scope the calling key does not hold returns 422 with per-field errors — there is no silent narrowing: the key is not created with a trimmed scope list, the whole request fails.

{
  "error": {
    "type": "validation_error",
    "code": "validation_failed",
    "message": "No puedes conceder un scope que tu propia key no tiene.",
    "param": "scopes"
  }
}

So a key holding invoices:read invoices:write can mint child keys with any subset of those two scopes, but never clients:write. Provision a sufficiently scoped master key first, then derive narrower child keys from it. The environment and tier are never taken from the body — they are inherited from the calling key.

FieldRequiredNotes
nameyesHuman-readable label (1–120 chars).
scopesyesOne or more scopes, each a subset of the calling key's scopes.
expires_atnoFuture ISO 8601 instant after which the key stops authenticating.
ip_allowlistnoOptional list of allowed IPs / CIDR ranges (IPv4, IPv6, /N).

Rotate the secret

POST /v1/companies/{id}/api-keys/{key}/rotate-secret invalidates the current secret immediately, generates a fresh prefix + secret, and returns the new secret in plaintext exactly once. Requires the api_keys:write scope.

curl -X POST \
  https://api.factuarea.com/v1/companies/01931b3e-7c4a-7f2e-9a8b-4d6e7f8a9b0c/api-keys/0190f2c0-77aa-7b21-8c33-1d2e3f405162/rotate-secret \
  -H "Authorization: Bearer fact_live_8KqW3pXnR2VbY7TcA9eFmN5z"

Rotation takes effect right away: any request still using the old secret stops authenticating the instant you rotate. Deploy the new secret before — or atomically with — the rotation to avoid downtime. This is irreversible.

Revoke a child key

DELETE /v1/companies/{id}/api-keys/{key} revokes a child key permanently. Subsequent requests authenticated with it stop working. Requires the api_keys:write scope.

curl -X DELETE \
  https://api.factuarea.com/v1/companies/01931b3e-7c4a-7f2e-9a8b-4d6e7f8a9b0c/api-keys/0190f2c0-77aa-7b21-8c33-1d2e3f405162 \
  -H "Authorization: Bearer fact_live_8KqW3pXnR2VbY7TcA9eFmN5z"

Revocation is irreversible. Once revoked, the key cannot be restored — mint a new one if the company still needs API access.

Scopes and isolation

Child keys are gated by the api_keys scopes:

  • api_keys:read — list and retrieve child keys.
  • api_keys:write — create, rotate and revoke child keys.

Every operation is scoped to your master tenant. A company id belonging to a different master returns 404 — never 403, and never a child-key endpoint for a company you do not manage. This is the same cross-master isolation that governs the companies themselves: a master can only ever see and act on its own companies and their keys.

On this page