Skip to content

Assignment provider apps

An assignment provider is an app that decides who does a task: a cleaning marketplace, a maintenance dispatcher, a staffing service. The host designates your app for a task type (say, cleaning); when such a task is created, Stayblox hands the assignment to you, you pick a worker using your own data, and you write the result back over the API.

The golden rule: your credentials and endpoints live on your server; Stayblox holds only the interface. Core Stayblox contains no provider-specific code; everything below works for any marketplace through the public API. We use Turno as the concrete example, but nothing here is Turno-specific.

For a complete runnable server, see the reference app.

1. Declare your app (manifest)

Register as a remote app that reads and writes tasks, holds the act_as_assignment_provider capability, and subscribes to task.assignment_requested. In your app.toml:

toml
type = "remote"
scopes = ["read_tasks", "write_tasks"]
capabilities = ["act_as_assignment_provider"]
webhooks = ["task.assignment_requested"]
webhook_url = "https://your-app.example.com/stayblox/webhooks"

Add register_task_types to capabilities if you also define your own task types (with their own checklist and custom-field schema). The host consents to scopes and capabilities at install; both are stored on the install and checked on every call (see Scopes & capabilities).

2. Get designated for a task type

The host designates your app as the assignment provider for a task type in their dashboard (Operations → Task types → Assignment provider). From then on, every task of that type that the platform creates (typically via a host-configured rule, e.g. "on checkout, create a cleaning task") is routed to you for assignment.

3. Receive the assignment request (platform → app)

When such a task is created, Stayblox POSTs a task.assignment_requested webhook to your webhook_url. The request is HMAC-signed; verify it before acting (see Signing & security). The envelope's resource identifies the task:

json
{
  "event_id": "01J…",
  "topic": "task.assignment_requested",
  "occurred_at": "2026-06-27T11:00:00Z",
  "api_version": "2026-01",
  "team": "8cs3o-qe",
  "resource": {
    "type": "task",
    "id": 42,
    "task_type": "cleaning",
    "canonical_status": "open",
    "property_id": 3,
    "booking_id": 88,
    "due_at": "2026-06-27T11:00:00Z"
  }
}

Fetch full task state any time with task(id) (read_tasks). Now schedule a worker on your side; Turno calls its own scheduling API on its own server. Stayblox never sees how you pick; it only sees the assignment you write back.

4. Write the assignment back (app → platform)

Call taskAssign with your bearer token to record the assignee. This needs the act_as_assignment_provider capability and moves the task OPEN → ASSIGNED. Store your own identifiers as namespaced custom fields so you can correlate later.

graphql
mutation Assign($id: ID!, $name: String!) {
  taskAssign(input: { id: $id, assigneeType: "app", assigneeName: $name }) {
    task { id canonicalStatus assigneeName }
    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!, $name: String!){ taskAssign(input:{ id:$id, assigneeType:\"app\", assigneeName:$name }){ task{ id canonicalStatus } userErrors{ message } } }",
    "variables": { "id": "42", "name": "Sparkle Cleaners" }
  }'

Then attach your identifiers:

graphql
mutation Tag($id: ID!) {
  taskSetCustomField(taskId: $id, namespace: "turno", key: "project_id", type: "string", value: "proj_42") {
    task { id }
    userErrors { message }
  }
}

5. Push status as the work progresses

As the job moves, transition the canonical status (and add photos/notes via checklist items or custom fields):

graphql
mutation Progress($id: ID!, $status: TaskStatus!) {
  taskTransitionStatus(id: $id, status: $status) {
    task { id canonicalStatus }
    userErrors { field message }
  }
}

Walk ASSIGNED → IN_PROGRESS → COMPLETED as your worker accepts, starts, and finishes. Every transition is validated; illegal moves come back in userErrors.

The fallback

If you don't write an assignment back within the host's SLA window, Stayblox falls back to its own built-in assignment so the task never stalls, and your later write-back is then a no-op. Respond promptly; treat the request as time-bound.

Guest-readiness

A property becomes guest-ready when its cleaning task reaches COMPLETED / VERIFIED, derived purely from canonical status, never from a label you set. So the single thing that flips a unit to "ready" is your taskTransitionStatus to COMPLETED.

Worked example: a cleaning marketplace (Turno)

End to end, with zero Turno code in Stayblox:

  1. The host designates the Turno app as the cleaning provider and keeps the default "on checkout, create a cleaning task" rule.
  2. A guest checks out → the rule creates a cleaning task → Stayblox emits task.assignment_requested to Turno's webhook_url.
  3. Turno schedules a cleaner via its own API on its own server, then calls taskAssign + taskSetCustomField(turno.project_id, …).
  4. As the cleaner accepts → starts → finishes, Turno pushes taskTransitionStatus through ASSIGNED → IN_PROGRESS → COMPLETED, attaching photos as it goes.
  5. The property flips to guest-ready off the canonical COMPLETED.

Turno's API keys and endpoints stay on Turno's server throughout. Stayblox stores only the assignment and the custom fields Turno chose to write.

Checklist

  • [ ] Manifest registered with type: remote, scopes: [read_tasks, write_tasks], capabilities: [act_as_assignment_provider].
  • [ ] Subscribed to task.assignment_requested; webhook_url set.
  • [ ] Webhook handler verifies the HMAC signature before acting.
  • [ ] Assignment written back with taskAssign (+ your ids via taskSetCustomField).
  • [ ] Status pushed with taskTransitionStatus as work progresses.
  • [ ] userErrors checked on every mutation.
  • [ ] Write-back happens within the host's SLA window (or the internal fallback takes over).

© Stayblox — Developer Platform