API Quickstart
Create a project, set up equipment operations, link a device, and share a TV playlist.
Create a workspace API key in MCP & API Keys and set DOZER_API_KEY. Every call below is rendered from the product's declared operations, so what you read is what the API answers.
Create the project with setup: true. Setup prepares equipment, locations, rosters, dashboards and a TV playlist from what you told it.
RESPONSE=$(curl --fail-with-body "https://trydozer.com/api/v1/projects" \
-H "Authorization: Bearer $DOZER_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: acme-projects.create-1' \
-d '{"setup":true,"name":"Acme Construction","prompt":"Equipment operations for our construction sites.","url":"https://example.com"}')
PROJECT_ID=$(printf '%s' "$RESPONSE" | jq -er '.project.id')
TASK_ID=$(printf '%s' "$RESPONSE" | jq -er '.setup.task.id')Read the setup task until run.status is terminal.
curl --fail-with-body "https://trydozer.com/api/v1/tasks/$TASK_ID" \
-H "Authorization: Bearer $DOZER_API_KEY" \
-H "Project-ID: $PROJECT_ID"The setup projection lists what was created — take the equipment and playlist ids.
RESPONSE=$(curl --fail-with-body "https://trydozer.com/api/v1/projects/$PROJECT_ID/setup" \
-H "Authorization: Bearer $DOZER_API_KEY" \
-H "Project-ID: $PROJECT_ID")
EQUIPMENT_ID=$(printf '%s' "$RESPONSE" | jq -er '.created.equipment[0]')
PLAYLIST_ID=$(printf '%s' "$RESPONSE" | jq -er '.created.playlists[0]')Link a real device serial to the equipment. Linked is not transmitting — read the device for last_live_data_at.
Set $DEVICE_SERIAL in your shell first.
curl --fail-with-body "https://trydozer.com/api/v1/devices/link" \
-H "Authorization: Bearer $DOZER_API_KEY" \
-H "Project-ID: $PROJECT_ID" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: acme-telemetry-devices.link-1' \
-d "$(jq -n --arg PROJECT_ID "$PROJECT_ID" --arg DEVICE_SERIAL "$DEVICE_SERIAL" --arg EQUIPMENT_ID "$EQUIPMENT_ID" '{"project_id":$PROJECT_ID,"links":[{"serial":$DEVICE_SERIAL,"equipment_id":$EQUIPMENT_ID,"source":"api"}]}')"A shareable TV link for the playlist.
curl --fail-with-body "https://trydozer.com/api/v1/display-shares" \
-H "Authorization: Bearer $DOZER_API_KEY" \
-H "Project-ID: $PROJECT_ID" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: acme-displays.share-1' \
-d "$(jq -n --arg PLAYLIST_ID "$PLAYLIST_ID" '{"kind":"playlist","object_id":$PLAYLIST_ID,"action":"read-or-create"}')"Reading work
GET /api/v1/tasks/{id} is the one read for anything asynchronous: the task with its latest run's receipt inlined as run — status, output, usage, cost_usd (null when unknown, never 0), a named error on failure, gaps on success (missing inventory, disconnected devices). Linking a device never claims it is transmitting; read the device and its last_live_data_at.
Retries and the advanced forms
Send the same Idempotency-Key with the same body to recover an acknowledgement. Unsure which equipment a serial belongs to: POST /devices/match-suggestions first. New hardware is provisioned through the HTTP-only POST /devices/provision or the Devices wizard; one-time credentials never reach a model tool. Product operations lists every route and typed model tool.