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.
The sample store
Section titled “The sample store”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) |
The tags in inventory
Section titled “The tags in inventory”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 |
Recent change messages
Section titled “Recent change messages”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 |
Organization
Section titled “Organization”Confirms which organization the token belongs to. Scope asset.read.
curl "https://api.vastvision.io/third-party-access/organization/" \ -H "Authorization: Bearer <YOUR_ACCESS_TOKEN>"{"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.
curl "https://api.vastvision.io/third-party-access/zones/" \ -H "Authorization: Bearer <YOUR_ACCESS_TOKEN>"[ {"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"}]Product catalog with counts
Section titled “Product catalog with counts”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.
curl "https://api.vastvision.io/third-party-access/asset-classifications-tiered/?return=asset_count" \ -H "Authorization: Bearer <YOUR_ACCESS_TOKEN>"{ "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 |
Recent movements
Section titled “Recent movements”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:
curl "https://api.vastvision.io/third-party-access/mqtt-change-messages/?limit=2" \ -H "Authorization: Bearer <YOUR_ACCESS_TOKEN>"[ { "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.
Stock alerts
Section titled “Stock alerts”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:
curl "https://api.vastvision.io/third-party-access/stock-alerts/?include_count=true" \ -H "Authorization: Bearer <YOUR_ACCESS_TOKEN>"[ { "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.