Skip to main content
PATCH

Authorizations

Authorization
string
header
required

Your secret API key as a Bearer token: Authorization: Bearer vxn_sk_.... Keys are created and scoped in the dashboard - see Authentication.

Headers

Idempotency-Key
string

Recommended on PATCH and DELETE for safe retries.

Required string length: 8 - 255

Path Parameters

id
string
required

Product identifier (prd_ prefix).

Pattern: ^prd_[A-Za-z0-9]+$

Body

application/json

Editable fields. pos_ref is never editable (owned by the sync); location_id is immutable (create a new entry at the other location). Archive with is_active: false - there is no DELETE.

name

New display name - plain string or per-language object (SET semantics on the whole value).

Required string length: 1 - 200
Example:

"Flat White"

sku
string | null

New correlation key (unique per location) - or null to clear.

Required string length: 1 - 64
category
string | null

New category, or null to clear.

Required string length: 1 - 100
tags
string[]

Replacement tag list (SET semantics).

price_minor
integer | null

New reference price, or null to clear. Maximum 100,000,000,000.

Required range: 0 <= x <= 100000000000
is_active
boolean

False archives the product (stays resolvable on historical line items).

Response

Updated product.

A catalog entry for correlating transaction line items to real products. Catalogs are per-location (each location can run a different POS with a different menu), unified under the organization: list org-wide, filter by location_id.

This is a loyalty correlation catalog, not an inventory system - no variants, modifiers, or stock levels.

id
string
required

Product identifier, prd_ prefix. Stable forever - line items resolve to it.

Pattern: ^prd_[A-Za-z0-9]+$
Example:

"prd_01HW9R7T2CD8N8MTX1RVPRDFW1"

object
string
required

Always "product".

Allowed value: "product"
location_id
string
required

The location this catalog entry belongs to. The same drink sold at two locations is two Product records (each mapped to its own POS).

Pattern: ^loc_[A-Za-z0-9]+$
Example:

"loc_01HW9R4P2ZK7N8MTX1RVLOCS01"

name
required

Display name - plain string or per-language object, the same localization pattern as Card.name. POS-synced entries arrive with the till's single-language name; supply per-language names on manual/API entries when your audience is multilingual (border stores, tourist areas). Notifications and future product-facing surfaces resolve the name in the customer's language.

Required string length: 1 - 200
Example:

"Flat White"

source
string
required

Where this catalog entry originated. Known values: pos (synced from the location's connected POS), manual (dashboard), api (created via POST /v1/products). Server-stamped - treat as an open set.

Example:

"pos"

is_active
boolean
required

False = archived (delisted from the POS or manually retired). Archived products stay resolvable on historical line items - there is no hard delete.

Example:

true

created_at
integer
required

Unix seconds.

Example:

1750000000

sku
string | null

Your stable key, unique per location (two locations may both use FW-12). This is what transaction line items correlate on.

Required string length: 1 - 64
Example:

"FW-12"

category
string | null

Free-form category for basket analytics.

Required string length: 1 - 100
Example:

"drinks"

tags
string[]

Merchant-owned filing aid, and part of the search haystack alongside the name. NEVER populated by POS sync: no POS system sends tags, so a source: "pos" entry arrives untagged. You can tag one yourself with PATCH /v1/products/{id} (tags are an overlay field, unlike pos_ref and source, which sync owns), and it becomes findable by that tag immediately. Sending [] clears them and removes them from the search haystack.

Example:
price_minor
integer | null

Reference price in minor units. Informational - the POS bill is authoritative at transaction time.

Required range: x >= 0
Example:

350

pos_ref
object | null

The POS mapping for this location's adapter. Read-only, owned by the sync - never editable via API. Null for manual/API entries. The POS vendor name is never surfaced.

Example:

null

updated_at
integer

Unix seconds of last change.

Example:

1750000000