API v1
Build on worksorder.ai
REST over HTTPS, JSON in and out. Raise work orders from your own systems, follow them through the pipeline, and pull quotes, invoices and certificates back — with signed webhooks pushing events to you as they happen. Use the reference below to connect your systems.
Open Settings → API in your portal.
Send JSON requests over HTTPS.
Receive signed webhook updates.
Base URL: https://app.worksorder.ai/api/v1
Authentication
Create a key in Settings → API in the portal (shown once — only a hash is stored). Send it on every request:
Authorization: Bearer wo_live_…
- Keys are firm-scoped and revocable at any time.
- Scopes default to everything; granular scopes (
work_orders:read,invoices:*, …) can be set per key. 401— missing, unknown or revoked key ·403— key lacks the scope.
Conventions
- Pagination:
?page=1&per_page=50(max 100). List responses:{ items, page, per_page, count }. - Times are UTC ISO 8601. Dates are
YYYY-MM-DD. - Errors:
{ "error": "message" }with a 4xx/5xx status. - Download links (
download_url,pdf_url) are signed and expire in ~10 minutes — fetch, don't store.
Work orders
| Method | Path | Notes |
|---|---|---|
| GET | /work-orders | Filters: status (csv), stage, updated_since, q (ref/title) |
| POST | /work-orders | Raise a job — see body below. external_ref dedupes, so retries are safe |
| GET | /work-orders/{id} | Full detail: visits, quotes, invoices, certificates (with downloads), events |
| POST | /work-orders/{id}/status | { "to": "scheduling", "reason": "…" } — portal transition rules apply |
| POST | /work-orders/{id}/notes | { "text": "…" } |
Raise a work order
POST /work-orders
{
"title": "EICR — 3 bed flat",
"job_type": "eicr",
"urgency": "routine",
"customer_id": "uuid (optional)",
"property_id": "uuid — or supply property:",
"property": { "address_line1": "14 Test St", "town": "Southend", "postcode": "SS1 1AA" },
"tenant": { "name": "…", "phone": "07…", "email": "…" },
"required_by": "2026-09-30",
"po_number": "PO-123",
"external_ref": "your-system-id-456"
}job_type values: eicr, eic, minor_works, gas_safety, boiler_service, epc, pat, fire_alarm, emergency_lighting, legionella, remedial_electrical, plumbing, heating, general_maintenance, other.
Pipeline stage values: attention, intake, booking, booked, on_site, sign_off, release, invoiced.
Customers
GET /customers (?q=name) · POST /customers · GET /customers/{id} (with properties and contacts)
Engineers & diary
GET /engineers · GET /visits?from=YYYY-MM-DD&to=YYYY-MM-DD
Money
GET /quotes (?status=sent,accepted) · GET /quotes/{id} (line items)
GET /invoices (?status=…) · GET /invoices/{id} (line items + signed pdf_url)
Compliance
GET /certificates (?kind=eicr&expires_before=YYYY-MM-DD)
GET /certificates/{id} — includes C1/C2/C3/FI observations and a signed download_url
Webhooks
GET /webhooks — list subscriptions · POST /webhooks — { "url": "https://…", "events": ["status_changed"] } (empty events = all; response includes secret once) · DELETE /webhooks/{id} — unsubscribe.
Deliveries are batches of work-order timeline events, POSTed to your URL within ~5 minutes:
{ "events": [ { "id": "…", "work_order_ref": "WO-000123", "kind": "status_changed",
"from_status": "booked", "to_status": "completed", "created_at": "…" } ] }Verify the wo-signature: sha256=<hex> header — an HMAC-SHA256 of the raw body with your webhook secret (compare case-insensitively, in constant time). Handlers must be idempotent; failed deliveries retry on the next run, and 10 consecutive failures deactivate the subscription (re-create to resume).
Get a key
API keys are self-served from Settings → API in the portal. Not a customer yet? Get in touch.
See it working
It starts with
one works order.
Start with a 10-minute introductory call about your business and the work you want to improve. If there’s a fit, we’ll arrange a one-hour session to scope your requirements and discuss a proposal.
Book a demo10 minutes · An introductory Google Meet call- ReceivedWorks order in01
- BookedTenant confirmed02
- CompletedSite records saved03
- InvoicedAgreed rates applied04