Skip to main content
Build a native room display integration that shows resource information, active and upcoming bookings, and allows on-premises booking creation via QR code or NFC. Capabilities:
  • Display room information and occupancy
  • Show active and upcoming bookings
  • Create bookings via QR code, NFC, or guest access
  • Check-in and check-out bookings

Pairing a New Display

1

Register or fetch the display panel

If no displayPanel UUID is stored on-device, register a new display:
Store the returned uuid and secret locally on-device. The response also includes meta.pairing_code and meta.public_url.If a UUID is already stored, fetch the existing panel:
2

Display pairing options

If displayPanel.organization is null, the panel is not yet paired. Show the 6-digit pairing_code from the response metadata and optionally a QR code:
Users can also enter the code manually at https://app.anny.co/displays/panels.
3

Subscribe to pairing updates

Subscribe to WebSocket updates to detect when the display is paired:The event payload contains the JSON:API-encoded display panel. Alternatively, poll GET /api/v1/display-panels/{uuid} on app startup.
4

Obtain a Bearer token

After pairing, the display panel includes a personal_access_token. Use this as the Bearer token for authenticated endpoints. Fetch the panel config on each app startup as the token may rotate.

Displaying the Grid

Display panels can show one or many resources simultaneously. Each resource is a widget in the widgets array of the display panel: Build a grid from the widgets. Use max_widgets_per_page to set page size, and provide pagination or auto-rotation if more widgets exist. secondary_widgets defines fallback resources shown when all primary resources are booked.

Load Resource Data

Load Booking Previews

Apply widget settings to the display:
  • Show/hide customer name based on showOrganizer
  • Show/hide booking description based on displayPanel.anonymize; use a generic “Booked” label when anonymized

Real-time Booking Updates

Join a private resource channel for each displayed resource using the panel’s Bearer token: On each WebSocket event, reload the booking previews for the resource.

Creating Bookings

Time Selection

Quick selection: Show up to 4 quick booking duration buttons.
  1. Find the service with the smallest min_duration
  2. Calculate options based on min_duration, max_duration, and booking interval
Example — min: 15, max: 60, interval: 15 → show 15, 30, 45, 60 Adhoc booking (when allowAdhocBooking is enabled): Start immediately at the current minute without time selection. Pass ?adhoc=true on the instant booking endpoint. Advanced selection:
  • GET /api/v1/resources/{id}/start-times — get available start times for a date
  • GET /api/v1/resources/{id}/end-times — get available end times for a selected start (flexible duration services)
Pass the QR code or NFC payload as a code query parameter:

Managing Bookings from the Display

Check-In

If the booking still needs check-in-timed legal documents or custom fields, send X-Supports-Dynamic-Form: true. The response meta.status is requires_details with a form_url. Collect the details, then call check-in again with form_data. Without the header the API returns HTTP 400 scans.check_in_requires_details_unsupported instead. The same delayed-form flow is available on POST /api/v1/scans — see X-Supports-Dynamic-Form and Scan.

Check-Out

Cancel

Bookings without an associated customer that are not blockers (is_blocker=false) can be cancelled directly from the display.

Extend Duration

Bookings can be extended if booking.charged_duration < service.max_duration.

Map Display Mode

When configured for map mode, the display shows an interactive floor plan. See the Map Client guide for the full implementation.

Unpairing

When the admin deletes the panel via the dashboard:
  • The app receives a .display-panels.deleted WebSocket event, or
  • GET /api/v1/display-panels/{uuid} returns 404
On either signal, clear the stored UUID and secret and return to the pairing screen.