A session represents a single verification flow against one tag. It’s the thread that connects one scan to the next so the platform can resolve them into one verdict.
Fields
| Field | Type | Notes |
|---|---|---|
id |
string | ses_-prefixed, assigned by the platform. |
inserted_at |
string | ISO 8601 timestamp when the session opened. |
A session belongs to a tag and groups the
verifications produced as the flow resolves: a
pending, then its valid / invalid resolution.
Where sessions come from
You don’t create a session directly. The platform opens one for you when a scan
arrives without a session relationship and returns its id in the verification
response, under data.relationships.session:
"relationships": {
"session": { "data": { "type": "sessions", "id": "ses_2cZuH8Cb7L5fseae6FzNDc" } }
}Using a session
Carry that session id back as the session relationship on a later scan so the
platform continues the session rather than starting a new flow:
"relationships": {
"session": { "data": { "type": "sessions", "id": "ses_2cZuH8Cb7L5fseae6FzNDc" } }
}See Verifications → Sessions and resolution for the full sequence.
A session is live for its tag’s session_duration: 10 minutes unless you
configured the tag otherwise. A scan after that window opens a
fresh session instead of resolving the old one. That response carries a new
session id and a pending verification. Store the new id.
The same happens when the session you send can’t be continued: an unknown id, a session that belongs to another tag, or one that has already resolved. The platform doesn’t return an error for these. It starts a fresh session, and the response shows a new session id. So compare the session id in each response with the one you sent, and replace yours when they differ.
Hand it to your coding agent
Paste the brief on Verifications. It is the one to give a coding agent before it writes the scan flow. The session rules inside it are these:
- Save the session id from the first verification before you answer the browser.
- Send that id back on the next tap as the
sessionrelationship. - On reload, read the saved id and show the verification you already stored. A reload does not open a session, and it does not POST the same tap again.
- When the session id in the response differs from the id you sent, the old
session is stale. Save the new id and show
pendingfor it.
When the page is built, run the checklist on Best practices.
Retrieve a session
GET /api/v1/sessions/:idFetch a session by id, with its tag as a relationship. The key
you present must own that tag, or the platform responds 404.
curl https://platform.tagbase.io/api/v1/sessions/ses_2cZuH8Cb7L5fseae6FzNDc \
-H "Authorization: Bearer $TAGBASE_API_KEY" \
-H "Accept: application/vnd.api+json"const res = await fetch(
"https://platform.tagbase.io/api/v1/sessions/ses_2cZuH8Cb7L5fseae6FzNDc",
{
headers: {
"Authorization": `Bearer ${process.env.TAGBASE_API_KEY}`,
"Accept": "application/vnd.api+json",
},
},
);
const session = await res.json();$response = $client->get("https://platform.tagbase.io/api/v1/sessions/ses_2cZuH8Cb7L5fseae6FzNDc", [
"headers" => [
"Authorization" => "Bearer " . getenv("TAGBASE_API_KEY"),
"Accept" => "application/vnd.api+json",
],
]);
$session = json_decode((string) $response->getBody(), true);session =
Req.get!("https://platform.tagbase.io/api/v1/sessions/ses_2cZuH8Cb7L5fseae6FzNDc",
headers: [
{"authorization", "Bearer #{System.fetch_env!("TAGBASE_API_KEY")}"},
{"accept", "application/vnd.api+json"}
]
).bodyResponse: 200 OK
{
"data": {
"type": "sessions",
"id": "ses_2cZuH8Cb7L5fseae6FzNDc",
"attributes": { "inserted_at": "2026-06-08T12:34:56.123456Z" },
"relationships": {
"tag": { "data": { "type": "tags", "id": "tag_XPg3Zq7gEExNezDWWW7Zzo" } }
}
}
}Errors
| Status | When |
|---|---|
401 |
Missing, invalid, or revoked key. |
404 |
No such session under your team. |
Notes
- A session can be fetched by id (above); there is no endpoint to list sessions. Otherwise it appears only as a relationship on a verification. Hold the id on your side for as long as the flow runs.