# Resource model

How teams, tags, sessions, and verifications fit together.


The platform exposes a small set of resources. Understanding how they relate is
enough to build almost any solution on top.

## The resources

- **Team**: who owns things. Your integration authenticates as a team.
  A team can create **subteams** beneath it, so you can give each customer
  or tenant its own isolated space and its own key.
- **API key**: how a team authenticates. A key belongs to exactly one
  team and only ever sees that team's data.
- **Tag**: the digital identity bound to a physical item. Tags belong to a
  team. A tag is what gets scanned.
- **Session**: one verification flow against a tag. A session groups the scans
  that make up a single check.
- **Verification**: the verdict for a scan, one of `pending`, `valid`, or `invalid`.
  Verifications belong to a session.

## How they relate

[Image: A team owns API keys and tags: one team, many keys, and one team, many tags. A tag has sessions, and a session has verifications.. See the web version of this page.]

- A **team** owns its **tags** and its **API keys**.
- A **tag** accumulates **sessions**, one per scan flow.
- A **session** holds the **verifications** produced as the flow resolves: a
  `pending`, later upgraded to `valid` or `invalid`.

## Subteams: multi-tenant by design

Teams nest. The team that owns your API key is your **root team**;
every team you create through the API becomes a **subteam** of it, with a
fresh key of its own.

This is the tenancy primitive. A solution typically provisions one subteam per
end customer, stores that subteam's key, and provisions that customer's tags
under it. Because a key only sees its own team's tags, tenants are isolated
from each other automatically: a scan validated with one subteam's key can
only ever resolve a tag that subteam owns.

Teams and subteams exist for two reasons:

- **Sandbox separation.** Sandbox is a property of the *team*, never of an
  individual tag. A team is either a sandbox team or a production team, so
  production tags and virtual tags can never appear side by side in the same
  team.
- **Billing and quota boundaries.** A team is the unit a bill attaches to: a
  team could be a company, a customer, a legal entity. A multi-tenant solution
  that needs separate billing per tenant is structured correctly by giving
  each tenant its own team.

Teams are strict access boundaries, and access is never inherited: a
dashboard user sees only the teams they are a member of. Root-team
membership grants nothing on its subteams: each membership is granted
per team, explicitly.

## Identifiers

Every resource has a prefixed, URL-safe id you'll see throughout the API:

| Resource     | Id prefix | Example                |
|--------------|-----------|------------------------|
| Team         | `tea_`    | `tea_UUkZTHiaPbRKiiJ4VLfCgF` |
| API key      | `key_`    | `key_VfUttEQbh1ceW7jtwV66rF` |
| Tag          | `tag_`    | `tag_XPg3Zq7gEExNezDWWW7Zzo` |
| Session      | `ses_`    | `ses_2cZuH8Cb7L5fseae6FzNDc` |
| Verification | `vrf_`    | `vrf_AoNAiMHGpUb2fxAB93eM4R` |

The prefix tells you the type at a glance; treat the whole string as an opaque
identifier.

