Fibric. Docs fibric.io →
v1.0.0 ยท stable
Reference

Authentication

Every request to the Fibric API authenticates with a secret API key sent as a Bearer token. The key does three jobs at once: it proves who you are, it names the one tenant you can touch, and it carries the scopes that decide what you can do there. This page covers key anatomy, live and test modes, workspace scoping, least-privilege roles, and rotation. Managing keys over the API itself is documented in the API keys reference.

Shared conventions, including the base URL, pagination, the Idempotency-Key header, and the error envelope, are defined in the API overview. Error codes are catalogued in Errors.

The Authorization header

Send the key in the Authorization header on every request. There is no cookie auth, no query-string token, and no unauthenticated endpoint in the API.

curl
curl https://api.fibric.io/v1/operators \
  -H "Authorization: Bearer sk_live_3f9c2a7b8e1d4f60a2c9"

Requests without the header, or with a token the server does not recognize, fail with 401; see 401 codes. A valid key calling a route outside its scopes fails with 403 insufficient_scope.

Key anatomy

Keys are opaque strings with a mode prefix. Never parse anything beyond the prefix; length and alphabet may change within a major version.

PrefixModeBehavior
sk_live_LiveReads and writes the tenant's real data. Side effects reach real connected systems, gated by governance as always.
sk_test_TestOperates on a sandboxed copy of the tenant: events, plans, and receipts are real objects in an isolated test partition, and connector side effects run against each connector's test transport instead of the live system. Test data never mixes with live data.

Live and test are parallel worlds with the same API surface. An id minted in test mode does not resolve with a live key, and the reverse; the mismatch reads as 404 not_found, the same as any cross-boundary id.

!
Secrets are shown once

The full secret is returned exactly once, at creation. The API and the console store only a hash and a display hint such as sk_live_…a2c9. Keys never appear in receipts, error messages, or logs. If a secret is lost, revoke the key and mint a new one; there is no recovery.

Tenant and workspace scoping

A key belongs to exactly one tenant. The server derives tenant_id and reseller_id from the key on every request and stamps them onto every object it writes. Nothing in a request body can widen this: a body that carries a mismatched tenant_id or reseller_id is rejected with 403 tenant_mismatch, and ids belonging to other tenants read as 404 not_found. The isolation model is described in Tenancy & isolation and the Tenants API.

Within a tenant, a key may optionally be pinned to one workspace. A workspace-pinned key behaves as if the tenant contained only that workspace:

Scopes

Scopes are granted per endpoint group and split read from write. Each endpoint's route bar names the scope it requires. The full grant is the union of the scopes on the key; there is no implicit escalation, and receipts has no write scope at all because the ledger is append-only and only the kernel appends.

ScopeGrants
events:read / events:writeList and retrieve events; ingest envelopes.
operators:read / operators:writeList and retrieve operators; create, update, pause, resume.
connectors:read / connectors:writeList and retrieve connectors; install, test, uninstall.
plans:read / plans:approveList and retrieve plans; approve or veto proposed plans.
actions:read / actions:writeList actions; undo an applied action.
receipts:readList, retrieve, and export receipts.
guardrails:read / guardrails:writeRead and manage guardrail policies; run dry-run evaluations. See the Guardrails API.
webhooks:read / webhooks:writeRead and manage webhook endpoints and deliveries. See the Webhooks API.
search:readQuery the search index across events, entities, and receipts. See the Search API.
tenants:read / tenants:writeRead tenant and workspace settings; manage members. See the Tenants API.
keys:read / keys:writeList keys; create and revoke keys. See the API keys reference.

Least-privilege key roles

Rather than assembling scope lists by hand, create keys from a role. A role is a named preset that expands to a fixed scope set at creation time; the key stores the expanded scopes, so a later change to a role's definition never silently changes an existing key.

RoleExpands toUse for
read_onlyEvery :read scopeDashboards, monitoring, audit tooling. Cannot cause any side effect.
ingestevents:writeWebhook receivers and gateways that push envelopes in. Cannot read anything back.
operateAll :read plus plans:approve, actions:writeHuman-in-the-loop tooling that approves, vetoes, and undoes. Cannot change operators, connectors, or guardrails.
adminEvery scopeProvisioning and configuration automation. The only role that can manage keys, tenants, guardrails, and webhooks.

Grant the smallest role that does the job, one key per workload. A key used by three services is three incidents wide; three ingest keys are each one revocation wide. The API keys page collects the operational practices.

i
Scopes are not guardrails

Scopes bound what an API caller may request. Guardrails bound what the executor will run, regardless of who asked. An admin key that approves a plan still cannot make a BLOCK verdict execute; the trust policy fails closed beneath every scope. See Governance & trust.

Key rotation

Rotation is overlap, cut over, revoke. Because a tenant can hold multiple active keys with identical scopes, rotation needs no downtime:

  1. Create a new key with the same role as the old one (create a key).
  2. Deploy the new secret to every workload that used the old one.
  3. Watch the old key's last_used_at until it stops advancing (list keys).
  4. Revoke the old key (revoke a key). Revocation is immediate: the next request with the old key fails with 401 key_revoked.
bash · a scripted rotation
# 1. mint the replacement with the same role
curl -s -X POST https://api.fibric.io/v1/keys \
  -H "Authorization: Bearer $FIBRIC_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: rotate-ingest-2026-07" \
  -d '{"name": "ingest-gateway-2026-07", "role": "ingest"}' | jq -r '.secret'

# 2. deploy, then confirm the old key has gone quiet
curl -s https://api.fibric.io/v1/keys/key_4e12ab \
  -H "Authorization: Bearer $FIBRIC_ADMIN_KEY" | jq '.last_used_at'

# 3. revoke the old key
curl -s -X DELETE https://api.fibric.io/v1/keys/key_4e12ab \
  -H "Authorization: Bearer $FIBRIC_ADMIN_KEY"

Rotate on a schedule that matches the key's blast radius, and rotate immediately on any suspicion of exposure. Key creation and revocation are themselves written to the receipt ledger, so a rotation leaves an audit trail.

Handling secrets in clients

Authentication errors

Every authentication failure uses the standard error envelope. The codes you will branch on:

StatusCodeWhen
401unauthenticatedThe Authorization header is missing or is not a Bearer token.
401key_invalidThe token is not a key the server recognizes. Check for whitespace, truncation, and live-versus-test mode.
401key_revokedThe key existed but has been revoked. Mint a new key and redeploy.
403insufficient_scopeThe key is valid but lacks the scope the route requires.
403tenant_mismatchThe body carried a tenant_id, reseller_id, or workspace_id that does not match the key.

None of these are retryable unchanged; fix the credential or the request first. The full retryability table is in Errors.