Skip to content
Dashboard

Check-in Instructions

An instruction is one step of the guided arrival or departure a guest follows in the guest portal: “Park in bay 3”, “Enter the side door with your code”, “Leave the keys on the counter”. Each step belongs to one stage, check_in or check_out, and to either one property or one property group. This guide covers managing those steps. Every field is listed on the operation’s page in the API Reference.

OperationRequestPermission
listInstructionsGET /instructionsview_properties
getInstructionGET /instructions/{id}view_properties
createInstructionPOST /instructionsmodify_properties
updateInstructionPATCH /instructions/{id}modify_properties
reorderInstructionPOST /instructions/{id}/reordermodify_properties
deleteInstructionDELETE /instructions/{id}modify_properties

Paths are relative to your region’s base URL, for example https://api-us.suiteop.com/api/v1. See Authentication for permissions.

A property’s guests see its group’s steps first, then the property’s own steps. Each scope keeps its own order; the two lists are never interleaved or deduplicated. There is no draft or publish state: the portal renders the stored steps, so a create, edit, reorder or delete shows on the guest’s next load.

Titles and descriptions can contain merge tokens, which the portal fills in per reservation: {{door_code}}, {{wifi_name}}, {{wifi_password}}, {{guest_name}}, {{checkin_time}}, {{checkout_time}}, {{address}} and {{host_name}}. A known token with no value renders empty. Anything else in double braces is shown as typed.

GET /instructions returns every matching step as a bare array under data. It is not paginated, so there is no limit, offset or meta.pagination. Steps come back in the order guests see them within their scope: by sortOrder, then creation time.

Terminal window
curl "https://api-us.suiteop.com/api/v1/instructions?propertyId=9a3d7e40-5b1c-4f2e-8d6a-1c2b3d4e5f60&type=check_in" \
-H "Authorization: Bearer sk_live_your_key_here"
{
"data": [
{
"id": "3f2b8c1d-7e4a-4b9f-a2c6-5d1e0f9a8b7c",
"type": "check_in",
"sortOrder": 0,
"title": "Find the side entrance",
"description": "Walk past the garden gate of Harbour Cottage and follow the path to the blue side door.",
"fixedCode": null,
"videoUrl": null,
"isAccessDisplayed": false,
"codeType": null,
"propertyId": "9a3d7e40-5b1c-4f2e-8d6a-1c2b3d4e5f60",
"propertyGroupId": null,
"deviceId": null,
"isTapToUnlockEnabled": false,
"imageUrl": "https://images.example.com/harbour-cottage/side-door.jpg",
"createdAt": "2026-07-01T09:12:44.000Z",
"updatedAt": "2026-07-01T09:12:44.000Z"
}
],
"meta": { "requestId": "…" }
}
FilterNotes
propertyIdOnly the property’s own steps. Its group’s steps aren’t included; list them with propertyGroupId
propertyGroupIdOnly the group’s shared steps (listPropertyGroups gives group IDs)
typecheck_in or check_out. Omit for both stages
(neither ID)Every step you can reach: property steps, group steps, and steps bound to neither. Check propertyId and propertyGroupId to tell them apart

To reconstruct what a guest of one property sees, list the group’s steps and the property’s steps separately and concatenate them in that order.

GET /instructions/{id} returns one step with the same fields. A step from another organization, or outside your property scope, returns 404.

title and description are always the English text, whatever languages your organization uses.

type, title and description are required, plus exactly one of propertyId or propertyGroupId. Sending both, or neither, is rejected with 400.

Terminal window
curl -X POST https://api-us.suiteop.com/api/v1/instructions \
-H "Authorization: Bearer sk_live_your_key_here" \
-H "Idempotency-Key: 7c9e6679-7425-40de-944b-e07fc1f90ae7" \
-H "Content-Type: application/json" \
-d '{
"type": "check_in",
"propertyId": "9a3d7e40-5b1c-4f2e-8d6a-1c2b3d4e5f60",
"title": "Open the side door",
"description": "Enter {{door_code}} on the keypad, then press the lock button.",
"isAccessDisplayed": true,
"codeType": "property_fixed_code"
}'

The response is 201, with the stored step under data:

{
"data": {
"id": "5e8a2f14-3c6b-4d7e-9f10-a1b2c3d4e5f6",
"type": "check_in",
"sortOrder": 1,
"title": "Open the side door",
"description": "Enter {{door_code}} on the keypad, then press the lock button.",
"fixedCode": null,
"videoUrl": null,
"isAccessDisplayed": true,
"codeType": "property_fixed_code",
"propertyId": "9a3d7e40-5b1c-4f2e-8d6a-1c2b3d4e5f60",
"propertyGroupId": null,
"deviceId": null,
"isTapToUnlockEnabled": null,
"createdAt": "2026-07-02T14:03:10.000Z",
"updatedAt": "2026-07-02T14:03:10.000Z"
},
"meta": { "requestId": "…" }
}
const res = await fetch('https://api-us.suiteop.com/api/v1/instructions', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.SUITEOP_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
type: 'check_out',
propertyId: '9a3d7e40-5b1c-4f2e-8d6a-1c2b3d4e5f60',
title: 'Leave the keys',
description: 'Please leave both keys on the kitchen counter and pull the door shut.',
}),
})
const { data } = await res.json()
const stepId = data.id

Field notes:

  • title is a single line of plain text, 1 to 500 characters. description is plain text or HTML rich text, 1 to 20,000 characters. Both are stored as the English source and machine-translated into your organization’s other languages in the background, so other languages can lag behind the response.
  • sortOrder is the zero-based position among steps of the same scope and stage. Omit it to append to the end. An explicit value doesn’t shift the other steps, so two steps can end up with the same position; use reorderInstruction to move a step instead.
  • videoUrl takes an http or https URL of up to 2,000 characters, an empty string, or null.
  • Images can’t be set through the API. imageUrl appears on listInstructions and getInstruction only; create and update responses don’t carry it.
  • The create and update responses echo the stored isTapToUnlockEnabled, which can be null (see below). The list and get responses return the resolved true or false the guest actually gets.

Four fields decide what code a step shows and whether it offers a one-tap unlock button:

FieldMeaning
isAccessDisplayedShows the resolved code on the step. Without it the code only appears where {{door_code}} is typed in the text
codeTypemanual_code (the step’s fixedCode), reservation_dynamic_code (the code issued for the stay), property_fixed_code (the property’s static code), group_fixed_code (the group’s static code), or null
fixedCodeLiteral text up to 200 characters. It provisions nothing on a lock. manual_code shows it; on property_fixed_code and group_fixed_code it overrides the static code
deviceIdThe lock the step is about, from listDevices. It picks which lock’s stay code reservation_dynamic_code shows, and which lock the unlock button opens. It must be a lock reachable from the step’s property or group
isTapToUnlockEnabledWhether the guest gets an unlock button. Check-in steps only: check-out steps are always stored as false. null means the button appears whenever deviceId is set

These combinations are rejected with 400 validation_error:

  • isAccessDisplayed: true with reservation_dynamic_code, or isTapToUnlockEnabled: true, without a deviceId, when the step’s property or group has a lock that could serve it. On a group step a device is always required for these.
  • A deviceId that isn’t a lock available to that property or group, or one that can’t display a dynamic code when reservation_dynamic_code is shown.
  • property_fixed_code on a group step without a fixedCode. Each property’s own code would otherwise appear under a shared building step.

The static property code isn’t shown while the property has isUnitCodeDisabled set (see Properties).

PATCH /instructions/{id} takes the fields to change inside a data object. Fields you leave out keep their current value; nullable fields take null to clear them.

Terminal window
curl -X PATCH https://api-us.suiteop.com/api/v1/instructions/5e8a2f14-3c6b-4d7e-9f10-a1b2c3d4e5f6 \
-H "Authorization: Bearer sk_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"data": {"title": "Open the blue side door", "videoUrl": "https://videos.example.com/harbour-cottage-entry.mp4"}}'

The response is the updated step, in the same shape as the create response.

  • Scope and stage can’t change. To move a step to another property or group, or from check-in to check-out, delete it and create it again.
  • Changing title or description replaces the other languages. The new English text is machine-translated again and overwrites every existing translation of that field, including ones written by hand. Resending the stored text unchanged is a no-op and re-translates nothing.
  • Clearing deviceId also turns the unlock button off on a check-in step, unless the same call sends isTapToUnlockEnabled.
  • The access-code rules above are checked when you pick a new device or newly turn on dynamic-code display or unlock. Edits that don’t touch access leave an older step’s settings alone.

POST /instructions/{id}/reorder moves one step and renumbers the rest of its scope and stage to 0, 1, 2, …:

Terminal window
curl -X POST https://api-us.suiteop.com/api/v1/instructions/5e8a2f14-3c6b-4d7e-9f10-a1b2c3d4e5f6/reorder \
-H "Authorization: Bearer sk_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"sortOrder": 0}'

The response is {"data": {"success": true}, "meta": {"requestId": "…"}}. A sortOrder past the last position puts the step at the end. Call listInstructions afterwards to read the new order.

DELETE /instructions/{id} removes the step permanently, along with its stored image file. There is no archive or undo. The remaining steps of the same scope and stage are renumbered from 0, so their sortOrder values change. The response is {"data": {"success": true}, "meta": {"requestId": "…"}}.

API keys reach every property. A credential limited to some properties (see Members) works within that reach:

  • Lists show only steps on its properties, on groups containing at least one of them, and steps bound to neither. Filtering by a property or group outside that reach returns an empty list, not an error.
  • getInstruction, updateInstruction, reorderInstruction and deleteInstruction return 404 for a step outside that reach.
  • createInstruction on a property outside the reach returns 404. On a group, it needs every property in the group, since the step appears to all of their guests; otherwise it returns 404.

An sk_ API key always reads fixedCode. An OAuth token acts as its member, and unless the token carries modify_properties or manage_lock_code (granted to the token and held by the member), listInstructions and getInstruction withhold a step’s fixedCode until 00:00 property-local time on the due day of an open task of theirs (as assignee or collaborator). For a property step the task must be at that property; for a group step, at any property of the group. A step bound to neither is always withheld from such a token. A task with no due date counts only while in_progress, and an overdue task keeps counting for up to 7 days.

A withheld step has fixedCode: null plus codeWithheld: true and codeRevealAt, the ISO 8601 instant the code becomes visible (null when no task of theirs will reveal it in the next 14 days, or none ever can, as for a step bound to neither). Both fields are absent when the code is returned, so a null fixedCode without codeWithheld simply means the step has none.