Appearance
Tasks
Tasks are the platform's operational work (cleanings, maintenance, inspections, restocks, concierge requests) and a first-class, extensible domain your app can read, create, automate, and extend. A task references a property (and optionally a reservation), carries a type, a canonical status, a checklist, an assignee, a cost, and your own namespaced custom fields.
This page covers reading and writing tasks. To act as an external assignment marketplace (Turno-style), see Assignment provider apps.
Canonical status
The platform owns a small, fixed status lifecycle. Apps may attach a displayLabel / substatus for richer UI, but all core logic keys off the canonical status only, never an app string.
OPEN → ASSIGNED → IN_PROGRESS → BLOCKED → COMPLETED → CANCELLED → VERIFIEDTransitions are validated: taskTransitionStatus returns a userError for an illegal move (e.g. OPEN → COMPLETED directly) rather than forcing it. A property's guest-readiness derives from a cleaning-type task reaching COMPLETED / VERIFIED.
Reading tasks
read_tasks unlocks task(id), tasks(filter, first, after), and propertyTaskCalendar(propertyId, from, to). Lists are forward-paginated by id cursor.
graphql
query Tasks($filter: TaskFilterInput) {
tasks(filter: $filter, first: 50) {
nodes { id type canonicalStatus title dueAt assigneeName }
pageInfo { hasNextPage endCursor }
}
}TaskFilterInput filters by propertyId, reservationId, type, canonicalStatus (a list), assigneeType / assigneeId, a due-date range, and updatedSince.
Resync after downtime
Pass filter.updatedSince (an ISO-8601 instant) to fetch every task changed at or after that time; this is the reconciliation query a backend uses to catch up after missing webhooks. Results stay id-ordered, so page through them the same way.
graphql
query Resync($since: String!) {
tasks(filter: { updatedSince: $since }, first: 100) {
nodes { id canonicalStatus updatedAt }
pageInfo { hasNextPage endCursor }
}
}Writing tasks
write_tasks unlocks the task* mutations. Each returns a { task, userErrors } result: check userErrors before treating the call as successful.
| Mutation | Purpose |
|---|---|
taskCreate | Create a task. |
taskUpdate | Update non-status fields. |
taskAssign | Set the assignee (provider write-back; needs act_as_assignment_provider). |
taskTransitionStatus | Move to a canonical status (validated). |
taskComplete / taskCancel | Shorthand transitions. |
taskAddChecklistItem / taskSetChecklistItemDone | Manage the checklist. |
taskSetCustomField | Set a namespaced, typed custom field. |
graphql
mutation Transition($id: ID!, $status: TaskStatus!) {
taskTransitionStatus(id: $id, status: $status) {
task { id canonicalStatus }
userErrors { field message }
}
}bash
curl -s https://api.stayblox.com/developer/api/2026-01/graphql \
-H "Authorization: Bearer $STAYBLOX_APP_TOKEN" \
-H "Content-Type: application/json" -H "Accept: application/json" \
-d '{
"query": "mutation($id: ID!, $status: TaskStatus!){ taskTransitionStatus(id:$id, status:$status){ task{ id canonicalStatus } userErrors{ message } } }",
"variables": { "id": "42", "status": "IN_PROGRESS" }
}'Custom fields
Custom fields are how your app stores its own state on a task without the platform modelling your domain. They are namespaced (use your app's prefix, e.g. turno) and typed (string, integer, float, boolean, date, datetime, json) so they stay queryable rather than being an opaque blob.
graphql
mutation SetField($taskId: ID!) {
taskSetCustomField(taskId: $taskId, namespace: "turno", key: "project_id", type: "string", value: "proj_42") {
task { id }
userErrors { message }
}
}Read them back on the Task.customFields field; value is stringified, parse it per its type.
Webhooks
Subscribe to the task.* topics (all require read_tasks) to react to task activity, then fetch current state with task(id):
| Topic | Fires when |
|---|---|
task.created | A task is created. |
task.assigned | A task gains an assignee. |
task.status_changed | Canonical status changes (carries from/to). |
task.completed | A task reaches COMPLETED. |
task.overdue | An active task passes its due date. |
task.assignment_requested | The platform asks a designated provider to assign a task (see Assignment provider apps). |
The exact required scope for each topic is listed in the Webhooks reference, and the full schema for every type and field is in the GraphQL reference.