Skip to content

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 → VERIFIED

Transitions 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.

MutationPurpose
taskCreateCreate a task.
taskUpdateUpdate non-status fields.
taskAssignSet the assignee (provider write-back; needs act_as_assignment_provider).
taskTransitionStatusMove to a canonical status (validated).
taskComplete / taskCancelShorthand transitions.
taskAddChecklistItem / taskSetChecklistItemDoneManage the checklist.
taskSetCustomFieldSet 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):

TopicFires when
task.createdA task is created.
task.assignedA task gains an assignee.
task.status_changedCanonical status changes (carries from/to).
task.completedA task reaches COMPLETED.
task.overdueAn active task passes its due date.
task.assignment_requestedThe 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.

© Stayblox — Developer Platform