REST API and integrations
The panel is a client of this API, so what a dispatcher can do on screen your integration can do over HTTP. Keys, signed webhooks and a realtime channel come with it rather than with the top plan.
1. Quick start
Create an API key in Settings, API, then send it as a Bearer token. Keys act with full company scope and are shown only once, at creation.
curl -H "Authorization: Bearer sk_live_your_key_here" \ https://api.servayo.com/api/v1/tickets
Every path below is relative to https://api.servayo.com/api/v1.
2. Authentication
Two credential types work in the same Authorization: Bearer header: user JWTs (from POST /auth/login) and developer API keys (sk_live_...). All requests are scoped to your company, and tenant isolation is enforced at the database layer with row-level security.
3. Endpoints
Jobs (tickets)
| Method | Path | What it does |
|---|---|---|
| GET | /tickets | List jobs (technicians see their own) |
| POST | /tickets | Create a job |
| GET | /tickets/{id} | Job details |
| PATCH | /tickets/{id} | Update fields or status |
Inbox and leads
| Method | Path | What it does |
|---|---|---|
| GET | /inbox | All incoming requests (calls, leads, screenshots, voice widget) |
| POST | /inbox | Create a lead manually |
| POST | /inbox/{id}/convert | Convert a lead into a job (dedups the customer) |
Calls and the AI agent
| Method | Path | What it does |
|---|---|---|
| GET | /calls | Call history |
| GET | /calls/{id} | Call with transcript and extracted fields |
| POST | /calls/simulate | Run a simulated inbound call through the configured agent |
| GET | /agents | AI agent configuration |
| PATCH | /agents/{id} | Update capabilities, rules, data collection |
Customers
| Method | Path | What it does |
|---|---|---|
| GET | /customers | Customer book |
| GET | /customers/{id} | Customer with contacts and job history |
| POST | /customers | Create (dedups by phone and email) |
Invoices, estimates and payments
| Method | Path | What it does |
|---|---|---|
| POST | /tickets/{id}/invoice | Create or fetch the job's invoice |
| POST | /invoices/{id}/lines | Add a line item |
| POST | /invoices/{id}/finalize | Freeze with the customer's signature (PDF and SHA-256) |
| POST | /invoices/{id}/pay | Create a payment link |
| POST | /tickets/{id}/estimate | Pre-work estimate flow |
| POST | /estimates/{id}/approve | Customer approval signature |
Configuration
| Method | Path | What it does |
|---|---|---|
| GET | /channels | Order channel directory |
| GET | /phone-numbers | Phone numbers with channel auto-tagging |
| GET | /organization | Organization settings |
| GET | /analytics/summary | KPIs |
| GET | /analytics/monthly | Monthly revenue and jobs |
4. Realtime
Subscribe to live events over WebSocket: job status changes, new leads, technician GPS.
const ws = new WebSocket("wss://api.servayo.com/api/v1/ws?token=YOUR_JWT");
ws.onmessage = (msg) => console.log(JSON.parse(msg.data));
// {"event": "ticket.updated", "at": "...", "payload": {"ticket_id": "..."}}5. Webhooks
Register an endpoint in Settings, API and Servayo posts the same events to it. The body is the JSON above. Every request carries X-Servayo-Event and an HMAC-SHA256 signature of the raw body in X-Servayo-Signature, computed with the secret shown once when the endpoint is created. Verify the signature before you trust the call.
import hmac, hashlib
def valid(raw_body: bytes, header: str, secret: str) -> bool:
digest = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(f"sha256={digest}", header)
# header = request.headers["X-Servayo-Signature"]Subscribe to a subset of events, or leave the list empty to receive all of them. Manage endpoints through GET /webhooks, POST /webhooks, DELETE /webhooks/{id}, and read the catalog from GET /webhooks/events.
| Event | Fires when |
|---|---|
| ticket.created | A job was created, by a person or by the API |
| ticket.updated | Status, assignment or amounts changed |
| lead.created | A request landed in the inbox |
| lead.converted | A request became a job |
| call.received | A call record was written |
| review.submitted | A customer left a rating |
| payment.succeeded | Reserved, not emitted yet. A recorded payment arrives as ticket.updated with status paid |
Two things worth knowing before you build on this. Delivery is best effort: the endpoint stores the status of the last attempt, there is no retry queue yet, so reconcile against the list endpoints when a delivery has to be certain. And the realtime channel carries one extra event that is not in the subscribable catalog, tech.location, emitted when a technician app posts a position during a shift.
6. Interactive reference
A live OpenAPI explorer with request and response schemas runs next to the API at https://api.servayo.com/docs.