Skip to content

Reading inventory data: a worked example

This page walks through the read routes using one small, made-up store. Every response below is what the API would return for exactly this data, so you can see how the pieces fit together.

Example Retail Co. (organization 42) has one location, Downtown Store (3), with one fixed reader (RDR-DOWNTOWN-01) covering three zones: Back Stock (11) and Sales Floor (12) are interior zones, and Exit (14) is an exit zone at the front door. It sells two products, each with sizes:

Classification ID Parent Price
Polo Shirt 101 79.00
↳ Small 102 Polo Shirt (101)
↳ Medium 103 Polo Shirt (101)
↳ Large 104 Polo Shirt (101)
Quarter-Zip 201 98.00
↳ Medium 202 Quarter-Zip (201)
↳ Large 203 Quarter-Zip (201)

Eight tagged items. The Ref column (the last four characters of each EPC) is used to refer to tags in the rest of this page. Tag A006 was tagged as a Polo Shirt without a size.

Ref EPC (epc_hex) Asset ID Classifications Current zone
A001 E2801170000002000000A001 5001 Polo Shirt › Small Sales Floor
A002 E2801170000002000000A002 5002 Polo Shirt › Small Back Stock
A003 E2801170000002000000A003 5003 Polo Shirt › Medium Sales Floor
A004 E2801170000002000000A004 5004 Polo Shirt › Medium Exit
A005 E2801170000002000000A005 5005 Polo Shirt › Large Back Stock
A006 E2801170000002000000A006 5006 Polo Shirt Back Stock
B001 E2801170000002000000B001 5007 Quarter-Zip › Medium Sales Floor
B002 E2801170000002000000B002 5008 Quarter-Zip › Large Exit

The five most recent movements recorded by the reader, newest first. The last two are items being read at the Exit.

Movement ID Tag Movement Read at
90005 A004 (asset 5004) Sales Floor → Exit 14:52:10 UTC
90004 B002 (asset 5008) Sales Floor → Exit 14:31:44 UTC
90003 A001 (asset 5001) Back Stock → Sales Floor 13:05:02 UTC
90002 A003 (asset 5003) Back Stock → Sales Floor 12:40:18 UTC
90001 B001 (asset 5007) Back Stock → Sales Floor 11:15:37 UTC

Confirms which organization the token belongs to. Scope asset.read.

Terminal window
curl "https://api.vastvision.io/third-party-access/organization/" \
-H "Authorization: Bearer <YOUR_ACCESS_TOKEN>"
200 OK
{"id": 42, "name": "Example Retail Co.", "topic": "<ORG_TOPIC>"}

Lists every zone with the reader and antenna ports that cover it. Scope zone.read. Cache this list and use it to turn zone IDs into names in your UI.

Terminal window
curl "https://api.vastvision.io/third-party-access/zones/" \
-H "Authorization: Bearer <YOUR_ACCESS_TOKEN>"
200 OK
[
{"id": 11, "name": "Back Stock", "antennas": [1], "device_id": 7, "hardware_id": "RDR-DOWNTOWN-01"},
{"id": 12, "name": "Sales Floor", "antennas": [2, 3], "device_id": 7, "hardware_id": "RDR-DOWNTOWN-01"},
{"id": 14, "name": "Exit", "antennas": [4], "device_id": 7, "hardware_id": "RDR-DOWNTOWN-01"}
]

Returns the classification tree with asset_count on every node. Scope asset_classification.read. This is the main way to show how many of each item are in inventory.

Terminal window
curl "https://api.vastvision.io/third-party-access/asset-classifications-tiered/?return=asset_count" \
-H "Authorization: Bearer <YOUR_ACCESS_TOKEN>"
200 OK
{
"results": [
{
"id": 101, "name": "Polo Shirt", "organization_id": 42, "parent_id": null,
"price": "79.00", "depth": 0, "groupings": [],
"asset_count": 6, "no_subclass_asset_count": 1,
"children": [
{ "id": 102, "name": "Small", "organization_id": 42, "parent_id": 101,
"price": null, "depth": 1, "groupings": [], "asset_count": 2 },
{ "id": 103, "name": "Medium", "organization_id": 42, "parent_id": 101,
"price": null, "depth": 1, "groupings": [], "asset_count": 2 },
{ "id": 104, "name": "Large", "organization_id": 42, "parent_id": 101,
"price": null, "depth": 1, "groupings": [], "asset_count": 1 }
]
},
{
"id": 201, "name": "Quarter-Zip", "organization_id": 42, "parent_id": null,
"price": "98.00", "depth": 0, "groupings": [],
"asset_count": 2, "no_subclass_asset_count": 0,
"children": [
{ "id": 202, "name": "Medium", "organization_id": 42, "parent_id": 201,
"price": null, "depth": 1, "groupings": [], "asset_count": 1 },
{ "id": 203, "name": "Large", "organization_id": 42, "parent_id": 201,
"price": null, "depth": 1, "groupings": [], "asset_count": 1 }
]
}
],
"total": 2
}

How to read the counts: Polo Shirt has asset_count 6, made up of Small 2, Medium 2, Large 1, plus no_subclass_asset_count 1 for tag A006, which has no size. Counts include every asset carrying the classification, wherever it was last read.

Product Size Count shown in your app
Polo Shirt Small 2
Polo Shirt Medium 2
Polo Shirt Large 1
Polo Shirt (no size) 1
Quarter-Zip Medium 1
Quarter-Zip Large 1

Returns the most recent change messages, newest first, each with the asset, its current zone, and its previous zone. Scope mqtt_change_message.read. With limit=2 you get the two Exit reads:

Terminal window
curl "https://api.vastvision.io/third-party-access/mqtt-change-messages/?limit=2" \
-H "Authorization: Bearer <YOUR_ACCESS_TOKEN>"
200 OK
[
{
"id": 90005, "epcHex": "E2801170000002000000A004", "event_type": "tagInventory",
"angle": null, "rotation": null, "latitude": null, "longitude": null,
"timestamp": "2026-10-28T14:52:10.481223+00:00",
"created_at": "2026-10-28T14:52:10.902117+00:00",
"asset": {"id": 5004, "name": "Peter Millar Polo", "epc_hex": "E2801170000002000000A004"},
"current_zone": {"id": 14, "name": "Exit"},
"previous_zone": {"id": 12, "name": "Sales Floor"},
"previous_angle": null
},
{
"id": 90004, "epcHex": "E2801170000002000000B002", "event_type": "tagInventory",
"angle": null, "rotation": null, "latitude": null, "longitude": null,
"timestamp": "2026-10-28T14:31:44.120554+00:00",
"created_at": "2026-10-28T14:31:44.560081+00:00",
"asset": {"id": 5008, "name": "Peter Millar Quarter-Zip", "epc_hex": "E2801170000002000000B002"},
"current_zone": {"id": 14, "name": "Exit"},
"previous_zone": {"id": 12, "name": "Sales Floor"},
"previous_angle": null
}
]

To decide what each movement means for your business, compare current_zone.id with the zones you care about. In this store, a movement whose current_zone.id is 14 (Exit) means the item was read at the door.

Returns par-level rules. With include_count=true, each rule also includes current_count. Scope stock_alert.read. In this store, one rule watches Small polos on the Sales Floor and one watches Large polos across the whole organization:

Terminal window
curl "https://api.vastvision.io/third-party-access/stock-alerts/?include_count=true" \
-H "Authorization: Bearer <YOUR_ACCESS_TOKEN>"
200 OK
[
{ "id": 7, "organization_id": 42, "asset_classification_id": 102, "scope_type": "zone",
"zone_id": 12, "min_threshold": 2, "created_at": "2026-09-01T12:00:00+00:00", "current_count": 1 },
{ "id": 8, "organization_id": 42, "asset_classification_id": 104, "scope_type": "organization",
"min_threshold": 3, "created_at": "2026-09-01T12:00:00+00:00", "current_count": 1 }
]

Both rules are below their threshold: only tag A001 is a Small polo on the Sales Floor, and only A005 is a Large polo. Note that rule 8 has no zone_id key, because null fields are omitted.