object: "qr_code".
Example
Identifiers
string
required
Always
"qr_code".string (uuid)
required
Stable UUID. Use this in
{id} path params — but public_slug is accepted there too.string
required
The short slug shown in the scan URL. 7–10 characters of
[a-zA-Z0-9]. Stable for the life of the code — never regenerated, never reused. Path params accept this in lieu of the UUID.string (url)
required
Fully qualified short URL. The address printed on the physical QR. Convenience field — derived from
public_slug.Label
string | null
Operator-facing label. Free-form. Not rendered to scanning visitors. Set it during print to keep dashboard navigation sane.
string | null
Free-form description. Operator-facing only.
Destination
object
required
Where scans redirect. Always present as an object. Exactly one of
chatbot, page, knowledge_base, or url is non-null when type is set.Knowledge
Knowledge linked to this QR code itself, on top of the chatbot’s own. When a visitor scans it and lands on a chatbot, the chatbot searches its own knowledge plus these articles and folders, so item-specific content (the manual for the TV in one room) lives here instead of on the shared chatbot. See Scan-specific knowledge. If the code belongs to a group, the group’s linked knowledge applies too.string[]
required
UUIDs of Articles linked to this QR code. Write the desired set with
article_ids and the join is fully replaced.string[]
required
UUIDs of Article Categories linked to this QR code. Every article inside a linked category and its sub-categories (now and in future) is included.
Status & group
string (uuid) | null
Parent QR Group id, or
null if the code stands alone. When the group’s destination_type is set and the code’s own destination_type is null, scans inherit from the group. Detach by PATCHing group_id to null.Stats
integer
required
Lifetime count of redirected scans. Increments on
qr_code.scanned. Read-only.string (datetime) | null
ISO 8601 timestamp of the most recent scan, or
null if never scanned. Read-only.Timestamps
string (datetime)
required
When the code was minted. ISO 8601.
string (datetime)
required
Last mutation timestamp. ISO 8601.
Scan object
GET /qr-codes/{id}/scans returns immutable scan rows in cursor-paginated reverse-chronological order.
object
required
Snapshot of where this specific scan went. Captured at scan time so historical rows survive future destination changes.
object
required
The merged query params from the redirect: static params on the QR (and group) merged with whatever the visitor brought on the short URL. Live values win on key collision.
object
required
Coarse geolocation derived from the visitor IP. All three fields may be
null if the lookup fails.string | null
Raw
User-Agent header from the visitor’s request. null when absent.IP address and
Referer are deliberately not exposed on the wire — they’re collected for fraud detection but kept internal.Properties and URL params
Both are flat lists of{ key, value, sort_order } rows hung off the QR. Replace as a set with PUT:

