Tag Lifecycle
The complete state machine that governs every QrioTag — from creation to activation, loss, recovery, and deactivation.
What this page covers
This page explains the 7 possible states a QrioTag can be in, the rules governing which transitions are allowed, who can trigger them, and how the enforcement works in code.
Every QrioTag goes through a series of states during its lifetime. The system enforces strict rules about which transitions are allowed, who can trigger them, and what happens at each step.
The 7 Tag Statuses
| Status | Description |
|---|---|
| PENDING_SETUP | Tag has been created (digitally or via order) but the owner has not yet completed a profile. Scanning shows a setup prompt. |
| ACTIVE | Tag is fully configured and linked to a profile. Scanning shows the owner's contact and recovery information. This is the normal operating state. |
| LOST | Owner has marked the item as lost. Scan alerts are enabled — every scan triggers a notification to the owner with the location and time. |
| FOUND | A finder has reported finding the tagged item. The owner has been notified and can arrange a return. |
| STOLEN | Owner has reported the item as stolen. The scan page shows a theft alert. Police report info may be attached. |
| DEACTIVATED | Owner or admin has permanently disabled the tag. Scans are still recorded but no profile information is shown. |
| EXPIRED | The FREE 5-year validity period has ended. The tag is read-only — scans are recorded but no active relay is shown. Upgrades to PRO reactivate the tag. |
State Diagram
(created digitally or via order)
|
v
PENDING_SETUP
|
(profile set up)
|
v
+---→ ACTIVE ←---+---+
| | | |
| [mark] | |
| / \ | |
| v v | |
| LOST STOLEN--+ |
| | \ | |
| v v | |
|FOUND +--→ ACTIVE |
| | |
+--+ |
| |
v |
DEACTIVATED -----→ ACTIVE (re-enabled)
|
v
EXPIRED (FREE only, after 5 years) ----→ ACTIVE (after PRO upgrade)Valid Transitions
This table shows every allowed status change. Any transition not listed here will be rejected with an INVALID_TRANSITION error.
| From | To | Who Triggers It | What Happens |
|---|---|---|---|
| PENDING_SETUP | ACTIVE | User | User completes their tag profile. Tag becomes fully functional. |
| ACTIVE | LOST | User | User marks the item as lost. Scan alerts are enabled. Owner can add a message and reward. |
| ACTIVE | STOLEN | User | User reports the item stolen. Can attach a police report reference number. |
| ACTIVE | DEACTIVATED | User / Admin | User disables the tag. Profile info is hidden but scans are still recorded. |
| LOST | FOUND | System / User | A finder scans the tag and contacts the owner, or the owner manually marks it found. |
| LOST | ACTIVE | User | Owner recovers the item themselves and marks it active again. |
| LOST | STOLEN | User | Owner determines the item was actually stolen, not just lost. |
| FOUND | ACTIVE | User | Owner confirms the item has been returned and reactivates the tag. |
| STOLEN | ACTIVE | User | Item is recovered. Owner reactivates the tag. |
| STOLEN | DEACTIVATED | User | Item is not recovered. Owner permanently deactivates the tag. |
| DEACTIVATED | ACTIVE | User / Admin | Owner or admin re-enables a previously disabled tag. |
| EXPIRED | ACTIVE | System | Owner upgrades to PRO. Tag reactivates automatically. |
Valid Transitions by Status
Transition Enforcement in Code
The valid transitions are defined in packages/core/src/constants.ts:
export const VALID_STATUS_TRANSITIONS: Record<string, string[]> = {
PENDING_SETUP: ['ACTIVE'],
ACTIVE: ['LOST', 'STOLEN', 'DEACTIVATED'],
LOST: ['FOUND', 'ACTIVE', 'STOLEN'],
FOUND: ['ACTIVE'],
STOLEN: ['ACTIVE', 'DEACTIVATED'],
DEACTIVATED: ['ACTIVE'], // Re-activated by owner or admin
EXPIRED: ['ACTIVE'], // Re-activated after PRO upgrade
};Every status change goes through the isValidTransition() function in packages/core/src/utils.ts. If you attempt an invalid transition, the API returns:
{
"success": false,
"error": {
"code": "INVALID_TRANSITION",
"message": "Invalid status transition from 'DEACTIVATED' to 'LOST'"
}
}API Endpoint
To change a tag's status, use:
curl -X PATCH http://localhost:4000/api/v1/tags/:id/status \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"status": "LOST",
"message": "Lost at Central Park",
"rewardAmount": 50
}'The request body fields depend on the target status:
| Field | Used With | Description |
|---|---|---|
status | All | The target status (required) |
message | LOST | A message to show on the scan page (optional) |
rewardAmount | LOST | Reward amount in USD (optional) |
policeReportNumber | STOLEN | Police report reference (optional) |
Automatic scan alerts
When a tag is in LOST or STOLEN status, every scan automatically creates a ScanAlert record and triggers a push notification and email to the owner with the scan location and time.
Was this page helpful?