Thing access model¶
How a thing becomes visible to an account, and how an account shares it with another
account. This is the model behind the /access/v1/… capability group; the endpoint
contracts are in the API reference and the commands in the
CLI reference.
The four objects¶
- Thing
A device, product, or piece of equipment registered on the platform. Things move through a lifecycle — see Thing lifecycle.
- Registrar
A manufacturing context owned by an account. Things are enrolled into a registrar. An account can have several (different factory lines, product categories).
- Repository
An account-owned collection of things — your view of the fleet. An account can have several, uniquely named within the account, and one is the default. A thing is in your repository because a reference row says so; that reference is what makes it visible to you.
- Scope
A named selection of things inside one repository. Scope is the only grouping concept: there are no device groups and no tag buckets. A same-repository union is just another scope; a cross-repository union is a set of grants, not one object.
The rules you have to obey¶
These are the invariants the API enforces. Design against them, not around them.
Visibility comes from the repository reference, never from the registrar. Registering a thing does not, on its own, authorize you to read it — and registration does NOT insert the reference that does. Measured (2026-10-08): an immediate owner-side read after enrollment returns
404 thing not found; the home reference appears only once the thing is PLACED into a repository (console Repositories → place, or the CLI step in getting-started). Nothing in the API lets “I registered it” stand in for “it is in my repository”, so do not build a client that assumes the two are the same relation. They diverge routinely: platform-owned shared devices belong to no tenant registrar, and a manufacturing-line registrar’s things are read by end-user accounts that never owned the line. As of #287/#291 this is literally enforced: the former registrar-diagnostic rescue has been deleted in both thinghub and thingio, and the caller’s account must hold a ThingReference before any attribute or telemetry read (reference necessary, permissions still required — reference alone grants nothing).A visibility miss is
404, not403. This is deliberate anti-enumeration: a403would confirm that a thing exists in someone else’s account. Do not treat404as “bad identifier” — on any thing-, scope- or grant-scoped route it equally means “not referenced into your repository”. Retrying with a corrected id is the wrong reflex; check your reference first. (Since #287/#291, a KNOWN thing for which your account holds no reference returns an explicit403 thing-reference-required— “check your reference first” as a named class — while an unknown thing stays404.)Removing the reference removes visibility, with no second path. There is no shadow route through the registrar relation, no cached grant, and no owner override on the tenant surface.
DELETE /access/v1/repositories/{repository_id}/things/{thing_id}is sufficient and immediate. (#287/#291 deleted the one shadow route that existed — the registrar-owner rescue — so this sentence is now literal.) One qualification applies to the twin event stream (GET /api/v1/twins/{thing_id}/events): revocation takes effect on the next subscribe — an already-open stream closes within 300 s.Everything account-scoped hangs off the repository. Scopes are repository-bound and grants are scope-bound, so deleting a scope cascades away the grants over it. Your default repository is materialized on first touch — a brand-new account can call
GET /access/v1/repositoriesand get a usable answer without a setup step.A grant delegates named capabilities, never a role. There is no reader / operator / admin tier to ask for. See the table below.
Authorization is decided centrally and fails closed. A
403means the platform decided your principal may not perform that action on that resource. Adding a role or a claim to your token cannot change the outcome, and a decision that cannot be reached is a denial, not an allow. See Identity, grants, and application access.
Requesting access you have not been given¶
Where the owner has not pre-granted, the grantee asks and the owner decides:
fgai provisioning access-requests-list
fgai provisioning access-requests-decide --id ar-123 --body '{"decision":"approve"}'
An approval issues a short-lived approval token; it expires, so approvals are acted on
promptly rather than banked. The request lifecycle is part of the provisioning
capability group.
Where things go next¶
The endpoint contracts → API reference
Every command, grouped by capability → CLI reference
Who a principal is, and how a decision gets made → Identity, grants, and application access
The lifecycle a thing moves through → Thing lifecycle
Narrowing a share to one app, or to usage counters → App-scoped telemetry and usage metering