DspatchDevelopers

Dspatch API

A clean REST API and signed webhooks for everything your business does on Dspatch — customers, jobs, recurring schedules, quotes, invoices, payments, crews and reports. Available on the Pro and Enterprise plans.

Base URL: https://dspatch.io/api/v1/ · Format: JSON · Version: v1 · Machine-readable spec: openapi.json

curl https://dspatch.io/api/v1/me/ \
  -H "Authorization: Bearer dsk_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Authentication

Create a key in your admin portal under Integrations → API & Webhooks. Keys act as your business (not as a person), carry only the scopes you give them, and are shown once. Send the key as a bearer token or in X-API-Key.

Authorization: Bearer dsk_live_...
# or
X-API-Key: dsk_live_...
Keep keys server-side. Revoke a key from Integrations the moment it may have leaked; a revoked key fails with 401 immediately.

Scopes

ScopeGrants
read:customersList and read customers and sites; /me
write:customersCreate and update customers
read:jobsList and read jobs (visits)
write:jobsCancel a visit that has not started
read:schedulesRecurring schedules
read:quotesQuotes, including the service agreement text
read:invoicesInvoices with their payments
write:invoicesRecord an offline payment (check, cash, bank transfer)
read:paymentsPayments across invoices
read:crewsCrews and members
read:reportsReport summary

Conventions

Errors & limits

StatusMeaning
400Validation problem — the body says what
401Missing, invalid or revoked key
403Key lacks the scope, or the plan does not include the API
404Not found in your business
429Rate limit: 600 requests per hour per key

Customers

GET /customers/ qactive · GET /customers/{id}/ (includes sites) · POST /customers/ · PATCH /customers/{id}/

curl -X POST https://dspatch.io/api/v1/customers/ -H "Authorization: Bearer dsk_live_..." \
  -H "Content-Type: application/json" -d '{"name":"Wausau Country Club","kind":"commercial","billing_email":"ap@wausaucc.com"}'

Sites

GET /sites/ customer

Jobs

GET /jobs/ statusfromtocustomer · GET /jobs/{id}/ · POST /jobs/{id}/cancel/

Statuses: draft, scheduled, in_progress, on_break, completed, ready_to_invoice, cancelled.

Recurring schedules

GET /schedules/ status · GET /schedules/{id}/ — rrule is an iCalendar recurrence rule (e.g. FREQ=WEEKLY;BYDAY=MO,WE,FR).

Quotes

GET /quotes/ status · GET /quotes/{id}/ — includes service_agreement.

Invoices

GET /invoices/ statuscustomer · GET /invoices/{id}/ (includes payments, amount_due, dispute fields) · POST /invoices/{id}/record-payment/

curl -X POST https://dspatch.io/api/v1/invoices/1203/record-payment/ -H "Authorization: Bearer dsk_live_..." \
  -H "Content-Type: application/json" -d '{"amount":"450.00","provider":"check","reference":"#1042"}'
Card payments cannot be recorded through the API — they are collected through Dspatch so they are verified. Offline providers: check, cash, bank_transfer, zelle, venmo, other.

Payments

GET /payments/ fromto — each payment carries verified.

Crews

GET /crews/ · GET /crews/members/

Reports

GET /reports/summary/ fromto — collected, verified collected, jobs completed/cancelled, labor cost, open invoice balance.

Me

GET /me/ — the business and this key's scopes and rate limit.

Webhooks

Add an https:// endpoint in your admin portal under Integrations → API & Webhooks, choose events, and keep the signing secret (shown once). Dspatch POSTs JSON:

{
  "id": 8812, "event": "invoice.paid", "created_at": "2026-10-05T15:21:08Z", "business_id": 1,
  "data": { "id": 1203, "customer": 5511, "status": "paid", "total": "450.00", "amount_due": "0.00", ... }
}

Events

customer.created · job.created · job.completed · job.cancelled · quote.sent · quote.accepted · quote.declined · invoice.created · invoice.sent · invoice.paid · payment.received · dispute.opened · dispute.resolved · schedule.ended — or * for all.

Verifying signatures

Headers: X-Dspatch-Event, X-Dspatch-Delivery, X-Dspatch-Timestamp, X-Dspatch-Signature. The signature is sha256= + HMAC-SHA256 of timestamp + "." + rawBody with your secret. Reject timestamps older than five minutes.

# Python
import hmac, hashlib
expected = "sha256=" + hmac.new(secret.encode(), f"{ts}.{raw_body}".encode(), hashlib.sha256).hexdigest()
ok = hmac.compare_digest(expected, request.headers["X-Dspatch-Signature"])
// Node
const crypto = require("crypto");
const expected = "sha256=" + crypto.createHmac("sha256", secret).update(`${ts}.${rawBody}`).digest("hex");
const ok = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(req.headers["x-dspatch-signature"]));

Retries

Respond with any 2xx within 10 seconds. Otherwise Dspatch retries after 1 minute, 5 minutes and 30 minutes. After 10 consecutive failures the endpoint is paused; resume it from Integrations. Every attempt is visible in the delivery log, and Send test posts a test.ping event.

Changelog

2026-10-05 — v1 launched: keys with scopes, customers, sites, jobs, schedules, quotes, invoices, payments, crews, reports, webhooks.

Questions or a feature you need? support@dspatch.io · Dspatch, Inc.