Webhooks and API
Protodesk's webhook events and REST API. Available on Pro and above. Authentication, event payloads, rate limits.
Last updated April 19, 2026
Protodesk exposes two integration surfaces:
- Webhooks — we POST events to your URL when things happen in your workspace
- REST API — you call our endpoints to read and write workspace data
Both are available on Pro and above.
Webhooks
Configure at Settings → Webhooks → "New webhook".
Fields
- URL — your HTTPS endpoint (must be HTTPS in production)
- Events — pick which events trigger this webhook (or "All events")
- Secret — we generate one; use it to verify signature (see below)
Event types
| Event | When it fires |
|---|---|
ticket.created |
A new ticket enters the workspace |
ticket.updated |
Ticket status, assignee, labels, or priority changes |
ticket.resolved |
Ticket moves to resolved |
ticket.reopened |
Resolved ticket is reopened |
message.received |
Customer replies on any channel |
message.sent |
Agent sends a reply |
customer.created |
New customer record |
customer.updated |
Customer profile changes |
ai.action |
Any AI action completes (triage, Ticket Context, Suggest, auto-resolve) |
sla.breach_imminent |
SLA timer within warning threshold |
sla.breached |
SLA has been breached |
More on the roadmap — ask if you need a specific one.
Payload
All events POST JSON with a consistent envelope:
{
"event": "ticket.created",
"timestamp": "2026-04-19T12:34:56.789Z",
"workspaceId": "wsk_xyz",
"data": {
"ticket": { /* full ticket object */ },
"customer": { /* embedded customer */ }
}
}
Signature verification
Every webhook request includes two headers:
X-Protodesk-Signature— HMAC-SHA256 of the raw body, hex-encodedX-Protodesk-Timestamp— Unix epoch ms
Verify in your handler (pseudocode):
import { createHmac } from "node:crypto";
const signature = req.headers["x-protodesk-signature"];
const timestamp = req.headers["x-protodesk-timestamp"];
const body = await req.text();
const expected = createHmac("sha256", WEBHOOK_SECRET)
.update(`${timestamp}.${body}`)
.digest("hex");
if (expected !== signature) throw new Error("Invalid signature");
if (Date.now() - Number(timestamp) > 5 * 60 * 1000) throw new Error("Replay");
Delivery guarantees
- At-least-once. We retry failed deliveries with exponential backoff for up to 24 hours (1m, 5m, 15m, 1h, 6h, 24h).
- Ordered per resource, not global. Events for the same ticket arrive in order; events across different tickets may interleave.
- Idempotency key. Every event has a unique
event_idin the envelope. Use it to dedupe on your side.
REST API
Base URL: https://api.protodesk.io/v1
Authentication
Generate an API key at Settings → API → "New key". Scoped to your workspace.
Authorization: Bearer pk_live_xxxxxxxxxxxx
Never expose API keys in client-side code. Use a server or a serverless function.
Endpoints (MVP)
| Method | Path | Purpose |
|---|---|---|
GET |
/tickets |
List tickets with filters (status, label, priority, assignee) |
GET |
/tickets/:id |
Get a single ticket with messages |
POST |
/tickets |
Create a ticket programmatically |
PATCH |
/tickets/:id |
Update status, assignee, labels, priority |
POST |
/tickets/:id/messages |
Send a reply |
GET |
/customers |
List customers |
GET |
/customers/:id |
Get a single customer + their tickets |
POST |
/customers |
Create or upsert a customer |
GET |
/knowledge/articles |
List knowledge base articles |
POST |
/knowledge/articles |
Create an article |
Full reference on the Docs homepage (coming soon — we're expanding as we ship endpoints).
Pagination
List endpoints return:
{
"data": [ /* items */ ],
"pagination": {
"nextCursor": "eyJpZCI6...",
"hasMore": true
}
}
Pass ?cursor=<nextCursor> to get the next page. Default page size: 50. Max: 200 (pass ?limit=200).
Rate limits
- 1,000 requests / minute per workspace (Pro)
- 5,000 requests / minute per workspace (Business)
- Custom (Enterprise)
Responses include:
X-RateLimit-Limit— your current per-minute limitX-RateLimit-Remaining— requests left in this windowX-RateLimit-Reset— Unix epoch ms when the window resets
Over-limit responses: 429 Too Many Requests with a Retry-After header.
Errors
All errors return JSON:
{
"error": {
"code": "ticket.not_found",
"message": "Ticket tck_xyz not found",
"details": { /* optional extras */ }
}
}
Common codes: auth.invalid_key, auth.insufficient_permissions, validation.failed, rate_limit.exceeded, <resource>.not_found.
What's not in the API yet
- Analytics / insight endpoints — on the roadmap
- Real-time SSE feed for inbox updates — on the roadmap (currently internal only)
- Bulk operations (mass update) — file a request if you need it
Summary
- Webhooks push events to you; REST API lets you pull + mutate
- HMAC-SHA256 signature verification on webhooks
- API keys authenticate REST; never expose client-side
- Rate limits scale with plan
Questions? Email us.
