Skip to main content
A QR Code is returned as a JSON object with 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.
article_ids and category_ids are replace-only. Send the full desired set every time; omit a field to leave it untouched; pass [] to detach everything. Every id must belong to your organization, or the request is rejected with 422 unprocessable. Linked knowledge only applies while this QR code sends visitors to a chatbot.

Status & group

string
required
One of unconfigured, active, inactive, archived. See lifecycle.
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:
Properties are operator metadata (venue, batch, channel). URL params are appended to the redirect at scan time — see URL param merge.