Webhooks turn your Zendesk account into a real-time notification engine. Instead of polling APIs for updates, webhooks push data to your systems the moment something happens: a ticket gets created, an agent updates a priority, or a customer submits feedback. But to build reliable integrations, you'll need to understand exactly what data Zendesk sends and how it's structured.
This guide breaks down the Zendesk webhook payload format from the ground up. You'll learn about the two types of webhooks Zendesk offers, the exact structure of event payloads, how to verify webhook authenticity, and practical implementation tips. Whether you're building a custom integration or connecting Zendesk to third-party tools, understanding these payload formats is essential.
At eesel AI, we process webhook data from Zendesk and other platforms to power intelligent automation. Getting the payload format right is the first step toward building robust, secure integrations.
The two types of Zendesk webhooks
Zendesk offers two fundamentally different webhook connection methods, and the choice you make determines your payload format options. You cannot change this decision later, so it's worth understanding both approaches upfront.
Event-subscribed webhooks
These webhooks subscribe directly to Zendesk system events. When a user gets created, a ticket status changes, or an organization updates, Zendesk automatically sends a webhook to your endpoint.
Here's what you need to know:
- HTTP method: POST only
- Request format: JSON only
- Payload structure: Fixed schema defined by Zendesk
- Best for: Real-time notifications about user, organization, help center, or messaging activity
The payload is predictable. Zendesk controls what data gets sent, which means less flexibility but also less room for configuration errors.
Trigger and automation webhooks
These connect to Zendesk's business rules: triggers and automations. You define exactly when the webhook fires based on ticket conditions.
Key characteristics:
- HTTP methods: GET, POST, PUT, PATCH, DELETE
- Request format: JSON, XML, or form-encoded
- Payload structure: Fully customizable using Liquid markup placeholders
- Best for: Ticket-based workflows with conditional logic
This approach gives you complete control over the payload. You decide what data to include and how to format it.
Choosing the right approach
| Factor | Event-subscribed | Trigger/automation |
|---|---|---|
| Flexibility | Low (fixed schema) | High (custom payloads) |
| Setup complexity | Simple | More complex |
| Use case | System-wide events | Ticket-specific workflows |
| Payload size | System-defined | 256 KB maximum |
If you need to react to ticket changes with custom logic, use trigger webhooks. For broader system events like user creation or messaging activity, event-subscribed webhooks are the better fit.
Anatomy of a webhook request
Every webhook request from Zendesk includes standard HTTP headers that provide metadata about the request. Understanding these headers is crucial for routing, logging, and security verification.
Standard headers
| Header | Description | Example |
|---|---|---|
x-zendesk-account-id | Your Zendesk account identifier | 123456 |
x-zendesk-webhook-id | Unique identifier for this webhook | 01F1KRFQ6BG29CNWFR60NK5FNY |
x-zendesk-webhook-invocation-id | Specific invocation ID | 8350205582 |
x-zendesk-webhook-signature | HMAC-SHA256 signature for verification | EiqWE3SXTPQpPulBV6OSuuGziIishZNc1VwNZYqZrHU= |
x-zendesk-webhook-signature-timestamp | ISO 8601 timestamp | 2021-03-25T05:09:27Z |
The signature headers are optional but recommended for production integrations. They let you verify that requests actually came from Zendesk and help prevent replay attacks.
Request structure differences
Event-subscribed webhooks always use POST with JSON payloads. The body contains the full event data in a standardized schema.
Trigger webhooks vary based on your configuration. A GET request might include parameters in the URL, while POST requests include a body formatted as JSON, XML, or form-encoded data depending on your settings.
Event payload structure and examples
Event-subscribed webhooks use a consistent JSON schema across all event types. Once you understand the structure, parsing any event becomes straightforward.
Standard event schema
Every event payload includes these top-level properties:
{
"type": "zen:event-type:ticket.created",
"account_id": 12514403,
"id": "2b24ef10-19d4-4740-93cf-8f98ec4776c0",
"time": "2099-07-04T05:33:18Z",
"zendesk_event_version": "2022-06-20",
"subject": "zen:ticket:12345",
"detail": { /* resource details */ },
"event": { /* change information */ }
}
| Property | Description |
|---|---|
type | The event type identifier |
account_id | Your Zendesk account ID |
id | Unique event ID |
time | When the event occurred |
zendesk_event_version | Schema version (currently "2022-06-20") |
subject | Domain and resource identifier |
detail | Full resource object |
event | What changed (for update events) |
Ticket created event
When a new ticket is created, Zendesk sends a payload like this:
{
"account_id": 22129848,
"detail": {
"actor_id": "8447388090494",
"assignee_id": "8447388090494",
"brand_id": "8447346621310",
"created_at": "2025-01-08T10:12:07Z",
"description": "I need help with my recent order",
"external_id": null,
"form_id": "8646151517822",
"group_id": "8447320466430",
"id": "5158",
"is_public": true,
"organization_id": "8447346622462",
"priority": "LOW",
"requester_id": "8447388090494",
"status": "OPEN",
"subject": "Order help request",
"submitter_id": "8447388090494",
"tags": ["order-help"],
"type": "TASK",
"updated_at": "2025-01-08T10:12:07Z",
"via": { "channel": "web_service" }
},
"event": {
"meta": {
"sequence": {
"id": 39313930383633353634323835,
"position": 1
}
}
},
"id": "cbe4028c-7239-495d-b020-f22348516046",
"subject": "zen:ticket:5158",
"time": "2025-01-08T10:12:07.672717030Z",
"type": "zen:event-type:ticket.created",
"zendesk_event_version": "2022-11-06"
}
The detail object contains the complete ticket record. The event object for creation events only includes metadata about the event sequence.
Status changed event
Update events include a more detailed event object showing what changed:
{
"event": {
"current": "OPEN",
"meta": {
"sequence": {
"id": 39313930383633353634323835,
"position": 1
}
},
"previous": "NEW"
}
}
The current and previous properties show the before and after values. For status changes, possible values include: NEW, OPEN, PENDING, HOLD, SOLVED, CLOSED, DELETED, ARCHIVED, and SCRUBBED.
Priority changed event
Priority events follow the same pattern:
{
"event": {
"current": "URGENT",
"meta": { "sequence": { "id": 39313930383633353634323835, "position": 1 } },
"previous": "NORMAL"
}
}
Priority values are: LOW, NORMAL, HIGH, and URGENT.
Comment added event
When someone adds a comment to a ticket:
{
"event": {
"comment": {
"author": {
"id": "8659716080510",
"is_staff": false,
"name": "John Smith"
},
"body": "Thanks for the quick response!",
"id": "8659716087550",
"is_public": true
},
"meta": { "sequence": { "id": 39313930383633353634323835, "position": 1 } }
}
}
The comment object includes the full text, author information, and visibility status.
Tags changed event
For tag updates, Zendesk shows what was added and removed:
{
"event": {
"meta": { "sequence": { "id": 39313930383633353634323835, "position": 1 } },
"tags_added": ["urgent", "vip"],
"tags_removed": ["pending-review"]
}
}
This structure makes it easy to track tag changes without comparing full arrays.
Trigger webhook payloads and placeholders
Trigger and automation webhooks give you complete control over the payload format using Liquid markup placeholders.
Common placeholders
| Placeholder | Description |
|---|---|
{{ticket.id}} | Ticket ID |
{{ticket.title}} | Ticket subject |
{{ticket.description}} | Ticket description |
{{ticket.status}} | Current status |
{{ticket.priority}} | Priority level |
{{ticket.requester.email}} | Requester email |
{{ticket.requester.name}} | Requester name |
{{ticket.assignee.email}} | Assignee email |
{{ticket.group.name}} | Group name |
{{ticket.organization.name}} | Organization name |
{{ticket.tags}} | Comma-separated tags |
{{ticket.created_at}} | Creation timestamp |
{{ticket.updated_at}} | Last update timestamp |
{{current_user.name}} | User who triggered the action |
Custom JSON payload example
You can construct custom payloads like this:
{
"event": "ticket_updated",
"ticket_id": "{{ticket.id}}",
"ticket_url": "{{ticket.url}}",
"subject": "{{ticket.title}}",
"description": "{{ticket.description}}",
"status": "{{ticket.status}}",
"priority": "{{ticket.priority}}",
"requester": {
"name": "{{ticket.requester.name}}",
"email": "{{ticket.requester.email}}"
},
"assignee": {
"name": "{{ticket.assignee.name}}",
"email": "{{ticket.assignee.email}}"
},
"tags": "{{ticket.tags}}",
"updated_by": "{{current_user.name}}"
}
Payload size limits
Custom payloads have a 256 KB maximum size. If your payload exceeds this limit, Zendesk truncates it. You'll want to keep an eye on payloads that include large description fields or many custom fields.
Authentication and security
Securing your webhook endpoints is critical. Zendesk provides multiple authentication options to verify incoming requests.
Signature verification
The most secure method uses HMAC-SHA256 signatures. Zendesk generates a signature from the timestamp and request body, which you can verify on your server.
Algorithm: base64(HMACSHA256(TIMESTAMP + BODY))
Node.js verification example:
const crypto = require("crypto");
const SIGNING_SECRET = "your_webhook_signing_secret";
const SIGNING_SECRET_ALGORITHM = "sha256";
function isValidSignature(signature, body, timestamp) {
let hmac = crypto.createHmac(SIGNING_SECRET_ALGORITHM, SIGNING_SECRET);
let sig = hmac.update(timestamp + body).digest("base64");
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(sig)
);
}
Python verification example:
import hmac
import hashlib
import base64
def verify_signature(payload, signature, timestamp, secret):
message = timestamp + payload
computed = base64.b64encode(
hmac.new(
secret.encode('utf-8'),
message.encode('utf-8'),
hashlib.sha256
).digest()
).decode('utf-8')
return hmac.compare_digest(computed, signature)
Signing secrets
Each webhook has a unique signing secret. You can retrieve it from the Zendesk Admin Center by clicking "Reveal secret" on the webhook details page, or via the API at GET /api/v2/webhooks/{id}/signing_secret.
For testing webhooks before creation, use this static secret: dGhpc19zZWNyZXRfaXNfZm9yX3Rlc3Rpbmdfb25seQ==
Additional authentication methods
Beyond signature verification, Zendesk supports:
- API key authentication: Add a custom header with your API key
- Basic authentication: Username and password or API token
- Bearer token: OAuth-style token authentication
Security best practices
- Always use HTTPS endpoints
- Verify signatures in production environments
- Validate timestamps to prevent replay attacks (reject requests older than 5 minutes)
- Store secrets in environment variables, never in code
- Make your webhook handlers idempotent (Zendesk may retry or send duplicates)
Testing and troubleshooting
Before deploying webhooks to production, you'll need reliable testing strategies.
Using webhook.site
Webhook.site provides a free, temporary URL that captures incoming requests. It's perfect for inspecting raw webhook payloads during development. You get a unique URL that displays headers and body content in real time.
Zendesk's built-in testing
When creating or editing a webhook in the Admin Center, Zendesk provides a test feature. You can send a test payload to your endpoint and see the response. This helps verify connectivity and payload format before going live.
Common errors and solutions
| Error | Cause | Solution |
|---|---|---|
| 401 Unauthorized | Authentication failure | Check API keys, tokens, or signature verification |
| 403 Forbidden | Endpoint rejected request | Verify endpoint accepts POST/GET as configured |
| 404 Not Found | Wrong endpoint URL | Double-check the webhook URL |
| Timeout | Endpoint too slow | Optimize response time or check server load |
| Circuit breaker triggered | Too many errors | Fix endpoint issues and wait for automatic reset |
Retry behavior
Zendesk retries failed webhooks automatically:
- HTTP 409 errors: up to 3 retries
- HTTP 429/503 with retry-after header under 60 seconds: retried
- Timeouts (12-second limit): up to 5 retries
The circuit breaker activates when 70% of requests fail within 5 minutes or more than 1,000 errors occur. It pauses the webhook for 5 seconds, then attempts one request. If successful, normal operation resumes.
Integrating webhooks with eesel AI
Webhooks become more powerful when combined with intelligent processing. At eesel AI, we help teams automate workflows by processing webhook data from Zendesk and other platforms.

Here's how webhook integration enhances support operations:
- Intelligent triage: Process ticket creation webhooks to automatically categorize and route tickets based on content analysis
- Automated responses: Trigger contextual replies using webhook data about ticket status and priority changes
- Data enrichment: Combine webhook payloads with internal data sources to provide agents with comprehensive customer context
- Cross-platform sync: Use webhooks to keep Zendesk in sync with CRM, inventory, or other business systems
Our Zendesk integration connects directly to your account, learning from your past tickets and help center to provide intelligent automation. Webhooks extend this capability by enabling real-time triggers and actions.
Key takeaways and best practices
Building reliable webhook integrations requires attention to detail. Here's what you'll want to remember:
Choose the right webhook type: Event-subscribed webhooks work best for system-wide notifications, while trigger webhooks give you flexibility for ticket-specific workflows.
Verify signatures in production: The HMAC-SHA256 signature verification ensures requests come from Zendesk and haven't been tampered with.
Handle retries gracefully: Zendesk may retry failed requests or send duplicates. Design your handlers to be idempotent.
Monitor webhook health: Use the activity log and circuit breaker status to catch issues early.
Test thoroughly: Use tools like webhook.site to inspect payloads before deploying to production.
Understanding the Zendesk webhook payload format is the foundation for building robust integrations. With the right approach to security, testing, and error handling, you can create reliable connections that keep your systems in sync and your team informed.
Frequently Asked Questions
Share this post

Article by
Stevia Putri
Stevia Putri is a marketing generalist at eesel AI, where she helps turn powerful AI tools into stories that resonate. She’s driven by curiosity, clarity, and the human side of technology.



