Skip to content

Managing inventory

The Inventory API registers and updates your physical inventory — locations (stores) and the devices (screens) deployed in them. A device also carries its own physical placement — its venue classification, zone, and product aisles.

Locations and devices each have their own endpoints:

Resource Upsert List
Locations POST /v1alpha/inventory/locations:upsert POST /v1alpha2/inventory/locations
Devices POST /v1alpha/inventory/devices:upsert POST /v1alpha/inventory/devices

Each :upsert takes the bare resource object as its request body — a locations:upsert body is a Location, a devices:upsert body is a Device.

  • Location — a physical store.
  • Device — a screen deployed at a location. Its physical placement — venue classification, zone, and product aisles — is owned by the device itself (see Venue, zones and aisles).
  • Upsert — every write is an idempotent create-or-update keyed on identity, so sending the same payload again simply reconciles state rather than creating duplicates.

metadata.id is server-generated and output-only — never send it on a write. metadata.name is yours, though: it follows the same full-replacement rule as any other field, so resend it on every upsert — omitting metadata clears a name already stored. Each resource is keyed on an identity you provide:

  • A location’s identity is its top-level externalId field. It is required on locations:upsert: the platform resolves an existing location by it, or creates one on a miss. Set the raw value — no externalid: prefix.
  • A device’s identity is its identifier (key + playerId); the device’s own externalId is derived from them as "{key}_{playerId}" and can’t be set directly. Both identifier (with a non-empty key and playerId) and status are required on devices:upsert.

An upsert response echoes the server-assigned metadata.id (a ULID). Use that ULID, or your own externalId, to reference the resource elsewhere.

The API reference marks required fields on each schema. “Required” is stated from the creating perspective: it is what a resource must carry the first time you upsert it.

Two rules decide whether a value counts as supplied:

  • Every enum has an *_UNSPECIFIED member, which is also its default. It means absent, never a value — so sending "status": "STATUS_UNSPECIFIED" on a required enum is rejected exactly as omitting the field is.
  • An omitted field and an explicitly empty one are the same thing (see write semantics), so an empty array does not satisfy a required repeated field.