Fibric. Docs fibric.io →
v0.9 ยท preview
Reference

Tenants API

A tenant is the unit of isolation in Fibric: every envelope, plan, action, and receipt is stamped with a tenant_id and, where one exists, a reseller_id above it. This page documents reading the tenant you authenticate as, managing workspaces within it, and managing members. The isolation model itself is described in Tenancy & isolation.

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

The reseller hierarchy

Three levels exist, and the API exposes exactly one of them to a key:

There is no reseller-level API surface in v0.9: a reseller administers each of its tenants with that tenant's own keys, and no key spans tenants. The reseller_id on your objects is informational, stamped for the audit trail, and appears on every envelope and receipt.

Isolation guarantees

The guarantees every endpoint honors, stated once here and assumed everywhere else in this reference:

GuaranteeMechanism
A key reads and writes exactly one tenant.Tenancy is derived from the key on every request, never from the body. See Authentication.
Cross-tenant existence is never disclosed.Another tenant's id reads as 404 not_found, indistinguishable from an id that never existed.
A body cannot widen the wall.A mismatched tenant_id, reseller_id, or workspace_id in a body is rejected with 403 tenant_mismatch.
Every stored row is stamped.reseller_id and tenant_id are columns on every row, enforced by row-level security in the store, not by application code alone.
Quotas and rate limits are per tenant.One tenant's burst cannot consume another's budget. See Rate limits & quotas.

The tenant object

idstring

Unique identifier, prefixed t_. The value stamped as tenant_id on every object the tenant owns.

objectstring

Always tenant.

namestring

Display name of the organization.

slugstring

URL-safe identifier, unique across the platform, for example acme-fulfillment. Immutable after provisioning.

reseller_idstring or null

The reseller this tenant belongs to. null means Fibric-direct. Immutable.

planstring

The commercial plan, for example early_access or team. Plan changes are made with your Fibric contact, not over the API.

workspacesobject[]

The tenant's workspaces, each with id, name, and created_at. Empty when the tenant does not partition.

created_atstring

RFC 3339 timestamp of provisioning.

json · the tenant object
{
  "id": "t_8f2ac901",
  "object": "tenant",
  "name": "Acme Fulfillment",
  "slug": "acme-fulfillment",
  "reseller_id": null,
  "plan": "early_access",
  "workspaces": [
    { "id": "ws_2d81f0", "name": "us-store", "created_at": "2026-05-01T10:00:00Z" },
    { "id": "ws_9a44c2", "name": "eu-store", "created_at": "2026-06-12T09:30:00Z" }
  ],
  "created_at": "2026-04-01T12:00:00Z"
}
GET

Retrieve the tenant

GET/v1/tenantscope tenants:read

Returns the tenant the calling key belongs to. The route is singular by design: there is no /tenants collection to list, because no key can see more than one.

curl
curl https://api.fibric.io/v1/tenant \
  -H "Authorization: Bearer $FIBRIC_KEY"

The response is the tenant object above. This endpoint is also the standard connectivity check: it is cheap, read-only, and exercises authentication end to end.

PATCH

Update the tenant

PATCH/v1/tenantscope tenants:write

Updates mutable tenant settings. Only name is mutable in v0.9; slug, reseller_id, and plan are not settable over the API.

namestring · body

New display name, 3–80 characters.

curl
curl -X PATCH https://api.fibric.io/v1/tenant \
  -H "Authorization: Bearer $FIBRIC_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Acme Fulfillment, Inc."}'

Error cases:

StatusCodeWhen
400invalid_parametername fails validation, or the body carries an immutable field such as slug.
403insufficient_scopeThe calling key lacks tenants:write.
POST

Create a workspace

POST/v1/tenant/workspacesscope tenants:write

Adds a workspace partition. Workspaces are lightweight: they add a workspace_id dimension to objects and keys, not a second wall. Hard isolation, separate quotas, separate members, separate receipts, is a second tenant, not a workspace.

namerequiredstring · body

Slug-style name, unique within the tenant. Lowercase letters, digits, and hyphens; 3–40 characters.

curl
curl -X POST https://api.fibric.io/v1/tenant/workspaces \
  -H "Authorization: Bearer $FIBRIC_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: ws-create-eu-store" \
  -d '{"name": "eu-store"}'
201 Created Response
json
{
  "id": "ws_9a44c2",
  "object": "workspace",
  "name": "eu-store",
  "created_at": "2026-06-12T09:30:00Z"
}

Error cases:

StatusCodeWhen
400invalid_parametername is not a valid slug.
409state_conflictA workspace with this name already exists in the tenant.

The member object

Members are the humans who sign in to the Fibric console: they approve plans, read receipts, and configure operators interactively. Members are distinct from API keys: a key authenticates a workload, a member authenticates a person, and both leave their identity in the audit trail (approver on receipts is a member email).

idstring

Unique identifier, prefixed mem_.

objectstring

Always member.

emailstring

The member's sign-in email, unique within the tenant.

rolestring

viewer (read everything, act on nothing), approver (viewer plus approve, veto, undo), or owner (approver plus manage operators, connectors, guardrails, members, and keys).

statusstring

invited until the member first signs in, then active. Removed members disappear from the list; their historical actions remain in receipts.

created_atstring

RFC 3339 timestamp of the invitation.

GET

List members

GET/v1/tenant/membersscope tenants:read

Returns the tenant's members, newest first, cursor-paginated with the standard limit and cursor parameters.

curl
curl https://api.fibric.io/v1/tenant/members \
  -H "Authorization: Bearer $FIBRIC_ADMIN_KEY"
200 OK Response
json
{
  "object": "list",
  "data": [
    {
      "id": "mem_7f01d3",
      "object": "member",
      "email": "l.ops@example.com",
      "role": "approver",
      "status": "active",
      "created_at": "2026-05-02T08:15:00Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
POST

Invite a member

POST/v1/tenant/membersscope tenants:write

Sends a console invitation. The member is invited until they first sign in.

emailrequiredstring · body

The invitee's email address.

rolerequiredstring · body

viewer, approver, or owner.

curl
curl -X POST https://api.fibric.io/v1/tenant/members \
  -H "Authorization: Bearer $FIBRIC_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: invite-l.ops" \
  -d '{"email": "l.ops@example.com", "role": "approver"}'

Error cases:

StatusCodeWhen
400invalid_parameteremail is not an email address, or role is not a known role.
409state_conflictA member with this email already exists in the tenant.
PATCH

Update a member

PATCH/v1/tenant/members/{member_id}scope tenants:write

Changes a member's role. Demoting the tenant's only owner fails with 409 state_conflict: a tenant always retains at least one owner.

DELETE

Remove a member

DELETE/v1/tenant/members/{member_id}scope tenants:write

Removes a member's console access immediately. Historical receipts naming the member as approver are unaffected; the audit trail does not rewrite. Removing the only owner fails with 409 state_conflict.

curl
curl -X DELETE https://api.fibric.io/v1/tenant/members/mem_7f01d3 \
  -H "Authorization: Bearer $FIBRIC_ADMIN_KEY"

Error cases for both endpoints:

StatusCodeWhen
404not_foundNo member with this id exists in the tenant.
409state_conflictThe change would leave the tenant with no owner.