{
"id": "<string>",
"type": "scans",
"attributes": {
"scan_type": "<string>",
"status": "<string>",
"device_identifier": "<string>",
"quantity": 123,
"meta": {},
"created_at": "<string>"
},
"links": {
"self": "<string>"
},
"relationships": {
"scannable": {
"data": {
"type": "<string>",
"id": "<string>"
},
"links": {
"self": "<string>"
}
},
"scanner": {
"data": {
"type": "<string>",
"id": "<string>"
},
"links": {
"self": "<string>"
}
}
}
}Scalar reference catalog
Scan
Create check-in and check-out scans for bookings (staff scanner, kiosk, or display). For the booking action endpoints, see Admin Booking Lifecycle.
On success the response is a
The
Create a scan
POST /api/v1/scans?o={org_id}&code={booking_code}&scannable_type=bookings
Authorization: Bearer {token}
X-Supports-Dynamic-Form: true
{
"data": {
"type": "scans",
"attributes": {
"scan_type": "check_in",
"device_identifier": "front-desk-scanner",
"latitude": null,
"longitude": null
}
}
}
Query parameters
| Parameter | Required | Description |
|---|---|---|
o | Yes | Organization ID |
code | Yes | Booking ticket / QR code |
scannable_type | No | Defaults to bookings |
allowed_resources | No | Restrict which base resources may be scanned |
Attributes
| Attribute | Required | Description |
|---|---|---|
scan_type | Yes | check_in or check_out |
device_identifier | No | Optional device label |
latitude / longitude | No | Geo coordinates when required by the resource |
meta.form_data | No | Delayed check-in details. Also accepted as top-level form_data (same shape as the booking check-in action). |
scans resource. A successful check-in also updates the booking’s check_in_date via the scan’s presence-date sync.
Statuses
| Status | Meaning |
|---|---|
valid | Scan succeeded; for check-in the booking is checked in |
requires_details | Check-in details (legal documents / custom fields) are still missing |
scanned | Already checked in (previous successful check-in exists) |
too_early / too_late | Outside the configured check-in window |
unpaid | Booking order is not fully paid |
invalid | Booking status does not allow check-in |
resource_not_allowed | Booking resource is outside allowed_resources |
Delayed check-in form data
When a booking still needs check-in-timed legal documents or custom fields, sendX-Supports-Dynamic-Form: true. Full header behaviour (booking action vs POST /scans) is in X-Supports-Dynamic-Form.
Without form payload:
- supported client → scan is created with
data.attributes.status: "requires_details"anddata.attributes.meta.form_url - unsupported client → HTTP 400,
scans.check_in_requires_details_unsupported
data.attributes.meta.form_url, then create another scan with the collected values as either top-level form_data or data.attributes.meta.form_data:
POST /api/v1/scans?o={org_id}&code={booking_code}&scannable_type=bookings
X-Supports-Dynamic-Form: true
{
"data": {
"type": "scans",
"attributes": {
"scan_type": "check_in",
"meta": {
"form_data": {
"documents": {
"{document_uuid}": { "accepted": true, "send_copy": false }
},
"service_custom_fields": {
"{field_uuid}": "value"
}
}
}
}
}
}
form_data object uses the same shape as POST /api/v1/bookings/{id}/check-in. Invalid values return HTTP 422. Submitted form_data is processed and not persisted on the scan record.
Related guides
- Admin Booking Lifecycle — booking check-in/out actions, Presence fields/endpoints, and X-Supports-Dynamic-Form
- Display Integration — room displays that check bookings in/out