The API is the product

The jobs, customers and schedules your team works with in the console are yours to read and write over HTTP. Create jobs, assign engineers and get told when something changes. Plain HTTP and JSON.

POST /v1/jobs HTTP/2
Authorization: Bearer ww_sk_live_4mQ8xR2vTn6Kd9Ls.••••
Idempotency-Key: 5c1f7a90-2e64-4b18-9d33-8af2c0e51b7d
Content-Type: application/json
 
{
"customer_id": "0198f0c4-6d3a-7b41-9f02-4c8e5b1f3a44",
"template_id": "0198f0c4-71aa-7c93-8d15-2b7e9c4d0a11",
"priority": "T_HIGH",
"scheduled_start": "2026-09-10T09:00:00Z"
}
 
# -> 201 Created
{ "data": { "id": "0198f0c4-8c04-7e35-b6a2-1f9d3e7c5b08",
"job_number": "JOB-00042",
"status": "T_PENDING" } }
The same job, in the consoleAssigned
WorkWing jobs board showing the day's jobs on the combined map and schedule view across all brandsWorkWing jobs board showing the day's jobs on the combined map and schedule view across all brands

Four ways in

WorkWing sits between your field team and the rest of your systems. Which route you take depends on which way the data needs to flow, and how much code you want to write.

REST API

Read and write jobs, customers, engineers and schedules over plain HTTP, with keys scoped to exactly what each integration needs. Calls work on the same live records as the console, inside the same organisation and brand boundaries.

Webhooks

Signed events pushed the moment something changes, and retried while your endpoint is down. Each delivery carries a key so you can spot a repeat.

Integration buttons

Put a button on a job form that calls your own API. Provision a service or raise a record in another system, without anyone leaving the job.

AI assistants

Connect an assistant over MCP and ask it to look up a customer, find a gap in someone's day or book a job. It acts as you, with your own permissions.

The endpoints most integrations start with

Resource-oriented endpoints with filtering, ordering and paging in the query string. Scheduling gets endpoints of its own, because moving a job through its lifecycle has rules that a plain update would skip.

All 124 operations in the reference →
GET/v1/jobsList and filter jobs
POST/v1/jobsCreate a job from one of your job types
PATCH/v1/jobs?id=eq.{id}Update one job, or many by filter
POST/v1/jobs/{id}/statusMove a job on, with the history written for you
POST/v1/jobs/{id}/assignmentsPut an engineer on a job
GET/v1/schedule/conflictsOverlapping assignments for a resource
GET/v1/resourcesThe field team, with their last known position
GET/v1/customersList and filter customers
GET/v1/jobs/{id}/trackingWhat your customer can see: the stage, the time window and an arrival estimate

What every call has in common

Four rules that hold across the whole API.

One base URL

Everything goes to one versioned address. Your organisation and your brand both come from the key, so that address is the same for every caller.

Writes are idempotent

Every write carries a key you generate. Send it twice inside a day and the first response comes back marked as a replay, rather than a second job.

Rate limits you can see

Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. Go over and you get a 429 with Retry-After.

Typed errors

One envelope for every failure, carrying a stable code worth branching on, a message for your log, and a request id you can quote back to us.

Webhooks

Subscribe an endpoint and WorkWing posts to it the moment something changes. Every delivery carries the event name, a timestamped HMAC-SHA256 signature of the exact body that a replayed copy fails, and an idempotency key that stays the same across retries. If your endpoint is down, we keep trying.

Job events carry the customer, the site and everyone assigned alongside the job, so most receivers never need a second call. Deliveries aren't ordered, and the same event can arrive twice, so treat each one as "something happened to this record" and read the record back when you need to know how it stands now.

Event catalogue · 24
  • job.created
  • job.updated
  • job.status_changed
  • job.completed
  • job.cancelled
  • job.failed
  • job.overdue
  • job.sla_response_breached
  • job.sla_resolution_breached
  • job.note_added
  • job.attachment_added
  • job.deleted
  • customer.created
  • customer.updated
  • customer.deleted
  • assignment.created
  • assignment.en_route
  • assignment.status_changed
  • assignment.on_site
  • assignment.completed
  • resource.location_updated
  • resource.status_changed
  • resource.created
  • resource.updated
delivery, job.completed
POST /hooks/workwing HTTP/1.1
X-Webhook-Event: job.completed
X-Webhook-Signature: t=1790000000,v1=4f8b1e7c9a02d3b5...
X-Webhook-Idempotency-Key: 0198f0c4-5a11-7c62-9d84-3e7b1f0c8a25

{
  "id": "0198f0c4-5a11-7c62-9d84-3e7b1f0c8a25",
  "event": "job.completed",
  "version": "2026-09-12",
  "created_at": "2026-09-10T11:04:18.902Z",
  "tenant_id": "0198f0c4-5a11-7c62-9d84-000000000001",
  "brand_id": "0198f0c4-5a11-7c62-9d84-000000000002",
  "data": {
    "job": {
      "id": "0198f0c4-5a11-7c62-9d84-000000000003",
      "number": "JOB-00042",
      "status": "T_COMPLETED",
      "previous_status": "T_IN_PROGRESS",
      "customer_id": "0198f0c4-5a11-7c62-9d84-000000000005",
      "completed_at": "2026-09-10T11:04:11.338Z"
    }
  }
}

Scoped API keys

Machine-to-machine auth with a bearer key. A key belongs to one brand and carries only the permissions you tick, and you can rotate one without downtime. Keys are shown once, when you create them.

Talk to it from Claude or ChatGPT

WorkWing has an MCP server at api.workwing.io/mcp. Add it as a connector, sign in, approve what it's allowed to do, and you can ask questions and book work in plain language. The assistant acts as you: it sees what you can see and does what you're allowed to do, in your own workspace.

How to connect an assistant →

Booking a job from Claude

Connect once, ask in plain English, and the job lands on the board, logged against the person who asked.

A custom integration, start to finish

Before work starts, Ashdown checks the client's purchase order with its finance system. The film follows the integration from the token in Secrets to the button on the job form.

Checking a purchase order before work starts1:09

Plain HTTP, from any language

There's no SDK to install. Send JSON with a key in the header from whatever you already write in, or generate a typed client from the OpenAPI document we publish.

  • Node.js
  • Python
  • Ruby
  • Go
  • PHP
  • .NET
  • Elixir
  • cURL

openapi.json →

The API is on every plan, the Free one included.