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.
| Operation | Endpoint | Scope |
|---|---|---|
| List child keys | GET /v1/companies/{id}/api-keys | api_keys:read |
| Create a child key | POST /v1/companies/{id}/api-keys | api_keys:write |
| Retrieve a child key | GET /v1/companies/{id}/api-keys/{key} | api_keys:read |
| Rotate the secret | POST /v1/companies/{id}/api-keys/{key}/rotate-secret | api_keys:write |
| Revoke a child key | DELETE /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.
| Field | Required | Notes |
|---|---|---|
name | yes | Human-readable label (1–120 chars). |
scopes | yes | One or more scopes, each a subset of the calling key's scopes. |
expires_at | no | Future ISO 8601 instant after which the key stops authenticating. |
ip_allowlist | no | Optional 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.