QrioTagQrioTag Docs
Flows & Examples

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

StatusDescription
PENDING_SETUPTag has been created (digitally or via order) but the owner has not yet completed a profile. Scanning shows a setup prompt.
ACTIVETag is fully configured and linked to a profile. Scanning shows the owner's contact and recovery information. This is the normal operating state.
LOSTOwner has marked the item as lost. Scan alerts are enabled — every scan triggers a notification to the owner with the location and time.
FOUNDA finder has reported finding the tagged item. The owner has been notified and can arrange a return.
STOLENOwner has reported the item as stolen. The scan page shows a theft alert. Police report info may be attached.
DEACTIVATEDOwner or admin has permanently disabled the tag. Scans are still recorded but no profile information is shown.
EXPIREDThe 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.

FromToWho Triggers ItWhat Happens
PENDING_SETUPACTIVEUserUser completes their tag profile. Tag becomes fully functional.
ACTIVELOSTUserUser marks the item as lost. Scan alerts are enabled. Owner can add a message and reward.
ACTIVESTOLENUserUser reports the item stolen. Can attach a police report reference number.
ACTIVEDEACTIVATEDUser / AdminUser disables the tag. Profile info is hidden but scans are still recorded.
LOSTFOUNDSystem / UserA finder scans the tag and contacts the owner, or the owner manually marks it found.
LOSTACTIVEUserOwner recovers the item themselves and marks it active again.
LOSTSTOLENUserOwner determines the item was actually stolen, not just lost.
FOUNDACTIVEUserOwner confirms the item has been returned and reactivates the tag.
STOLENACTIVEUserItem is recovered. Owner reactivates the tag.
STOLENDEACTIVATEDUserItem is not recovered. Owner permanently deactivates the tag.
DEACTIVATEDACTIVEUser / AdminOwner or admin re-enables a previously disabled tag.
EXPIREDACTIVESystemOwner 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:

FieldUsed WithDescription
statusAllThe target status (required)
messageLOSTA message to show on the scan page (optional)
rewardAmountLOSTReward amount in USD (optional)
policeReportNumberSTOLENPolice 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?

Tag Lifecycle | QrioTag Docs