Skip to content

Conventions

  • Requests and responses are JSON. Send Content-Type: application/json on every request that has a body, along with your Authorization header.
  • Use the paths exactly as documented, including the trailing slash (e.g. /zones/, not /zones).
  • Query parameters are standard URL query strings; booleans are true / false.
  • Timestamps are ISO-8601 strings with a timezone, in UTC, e.g. 2026-10-28T14:52:10.481223+00:00. Parse them with a timezone-aware parser and store them in UTC.
  • Most fields are snake_case. One exception: movement records return the tag as epcHex (camelCase) alongside a nested asset.epc_hex.
  • Prices are decimals with 2 places and may arrive as strings (e.g. "79.00"). Convert them explicitly rather than assuming a number.
  • Fields with no value are returned as null. Stock alert responses omit null fields entirely, so treat a missing key the same as null.
A typical request: stock counts for products matching "Polo"
curl "https://api.vastvision.io/third-party-access/asset-classifications-tiered/?return=asset_count&search_term=Polo" \
-H "Authorization: Bearer <YOUR_ACCESS_TOKEN>"

List routes use offset pagination with two query parameters:

Parameter Default Meaning
skip 0 How many records to skip from the start.
limit 5000 The maximum number of records to return.

Most list routes return a bare JSON array. If the array has fewer items than limit, you have reached the end. For example, to read zones 50 at a time:

GET /third-party-access/zones/?skip=0&limit=50 → 50 zones
GET /third-party-access/zones/?skip=50&limit=50 → 50 zones
GET /third-party-access/zones/?skip=100&limit=50 → 12 zones (fewer than 50: done)

The tiered classifications route is different. It returns an object with results and total, and both pagination and total apply to root classifications only. Each root is returned with all of its children nested beneath it, so one page can contain many more nodes than limit.

// GET /third-party-access/asset-classifications-tiered/?skip=0&limit=2
{
"results": [
{ "id": 101, "name": "Polo Shirt", "depth": 0, "children": [ /* Small, Medium, Large */ ] },
{ "id": 201, "name": "Quarter-Zip", "depth": 0, "children": [ /* Medium, Large */ ] }
],
"total": 2 // 2 root classifications in total, so there is no next page
}

The movements route (GET /mqtt-change-messages/) accepts limit only and always returns the most recent movements first. It is a recent-activity feed, not a full history to page through.

Errors return a JSON body of the form {"detail": "<message>"}. Validation errors return 422 with a detail array describing which field failed. Your client should handle detail being either a string or an array.

422 example (illustrative shape)
{
"detail": [
{
"loc": ["body", "asset_list", 0, "epc_hex"],
"msg": "string does not match regex",
"type": "value_error"
}
]
}

The EPC (Electronic Product Code) is the identifier encoded on each RFID tag and the unique key for an asset. It appears as epc_hex on assets and as epcHex on movement records.

  • Format: uppercase hexadecimal (0-9, A-F), 1 to 32 characters. Most retail UHF tags use a 96-bit EPC, which is 24 hex characters.
  • Uniqueness: an EPC is unique across the whole platform, not just your organization. If you send an EPC that already exists, that asset is not created and does not appear in the response.
  • Optional on create: leave epc_hex out and VastVision generates a unique EPC for you. This is the simplest choice when printing new labels, because the printer encodes whatever EPC the asset has.
  • Provide your own when items already carry pre-encoded tags, or when your system needs to control the numbering. Uppercase the value before sending it.
Value Valid? Why
E28011700000020F1A2B3C4D Yes 24 uppercase hex characters.
3034257BF7194E40 Yes 16 characters is within 1 to 32.
e28011700000020f1a2b3c4d No Lowercase. Send it uppercased.
E2801170-0000-020F No Hyphens are not hex characters.
E28011700000020F1A2B3C4D5E6F708192A3 No 36 characters is longer than 32.