Webhooks
Webhooks allow you to receive real-time notifications when events occur in Support Station. This enables you to build integrations that respond to ticket updates, new messages, and more. On this page, we will look at how to create, retrieve, update, and delete webhooks, as well as view delivery history.
The webhook model
The webhook model contains configuration for receiving event notifications.
Properties
- Name
id- Type
- string
- Description
Unique identifier for the webhook (UUID).
- Name
name- Type
- string
- Description
Human-readable name for the webhook.
- Name
url- Type
- string
- Description
The URL that will receive webhook POST requests.
- Name
secret- Type
- string
- Description
HMAC-SHA256 signing secret (only returned once on creation).
- Name
events- Type
- string[]
- Description
Array of event types this webhook is subscribed to.
- Name
is_active- Type
- boolean
- Description
Whether the webhook is currently active.
- Name
last_delivery_at- Type
- timestamp
- Description
Timestamp of the last delivery attempt (nullable).
- Name
last_delivery_status- Type
- string
- Description
Status of the last delivery:
successorfailed(nullable).
- Name
created_at- Type
- timestamp
- Description
Timestamp of when the webhook was created.
- Name
updated_at- Type
- timestamp
- Description
Timestamp of when the webhook was last updated.
Event Types
The following events can trigger webhook notifications:
- Name
ticket.created- Description
A new ticket was created.
- Name
ticket.updated- Description
A ticket was updated (status, priority, assignee, tags changed).
- Name
message.created- Description
A new message was added to a ticket.
List all webhooks
Returns a list of all webhooks in your organization.
Required scope: webhooks:read
Request
curl https://api.supportstation.io/api/v1/webhooks \
-H "Authorization: Bearer {token}"
Response
{
"data": [
{
"id": "webhook-uuid",
"name": "Production Webhook",
"url": "https://example.com/webhook",
"events": ["ticket.created", "ticket.updated"],
"is_active": true,
"last_delivery_at": "2025-01-15T10:00:00.000Z",
"last_delivery_status": "success",
"created_at": "2025-01-01T00:00:00.000Z",
"updated_at": "2025-01-15T10:00:00.000Z"
}
]
}
Retrieve a webhook
Returns a single webhook by ID.
Required scope: webhooks:read
Request
curl https://api.supportstation.io/api/v1/webhooks/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer {token}"
Response
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Production Webhook",
"url": "https://example.com/webhook",
"events": ["ticket.created", "ticket.updated"],
"is_active": true,
"last_delivery_at": "2025-01-15T10:00:00.000Z",
"last_delivery_status": "success",
"created_at": "2025-01-01T00:00:00.000Z",
"updated_at": "2025-01-15T10:00:00.000Z"
}
}
Create a webhook
Creates a new webhook. The webhook secret is only returned once in the response - make sure to store it securely for signature verification.
Required scope: webhooks:write
Required attributes
- Name
name- Type
- string
- Description
Human-readable name for the webhook (max 100 characters).
- Name
url- Type
- string
- Description
The URL that will receive POST requests.
- Name
events- Type
- string[]
- Description
Array of events to subscribe to. At least one event is required.
Request
curl -X POST https://api.supportstation.io/api/v1/webhooks \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"name": "My Integration",
"url": "https://example.com/webhook",
"events": ["ticket.created", "message.created"]
}'
Response
{
"data": {
"id": "new-webhook-uuid",
"name": "My Integration",
"url": "https://example.com/webhook",
"secret": "whsec_abc123def456...",
"events": ["ticket.created", "message.created"],
"is_active": true,
"created_at": "2025-01-15T10:00:00.000Z"
}
}
Store the secret securely - it will not be returned in subsequent API calls. You will need it to verify webhook signatures.
Update a webhook
Updates an existing webhook.
Required scope: webhooks:write
Optional attributes
- Name
name- Type
- string
- Description
New name for the webhook.
- Name
url- Type
- string
- Description
New URL for receiving events.
- Name
events- Type
- string[]
- Description
New list of events to subscribe to.
- Name
is_active- Type
- boolean
- Description
Enable or disable the webhook.
Request
curl -X PATCH https://api.supportstation.io/api/v1/webhooks/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"events": ["ticket.created", "ticket.updated", "message.created"],
"is_active": true
}'
Response
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "My Integration",
"url": "https://example.com/webhook",
"events": ["ticket.created", "ticket.updated", "message.created"],
"is_active": true,
"last_delivery_at": "2025-01-15T10:00:00.000Z",
"last_delivery_status": "success",
"created_at": "2025-01-01T00:00:00.000Z",
"updated_at": "2025-01-15T12:00:00.000Z"
}
}
Delete a webhook
Deletes a webhook. This will stop all event deliveries to this endpoint.
Required scope: webhooks:write
Request
curl -X DELETE https://api.supportstation.io/api/v1/webhooks/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer {token}"
Response
{
"data": {
"deleted": true
}
}
Get delivery history
Returns the delivery history for a webhook, showing past delivery attempts and their status.
Required scope: webhooks:read
Query parameters
- Name
page- Type
- integer
- Description
Page number (default: 1).
- Name
limit- Type
- integer
- Description
Items per page, max 100 (default: 20).
Request
curl https://api.supportstation.io/api/v1/webhooks/550e8400-e29b-41d4-a716-446655440000/deliveries \
-H "Authorization: Bearer {token}"
Response
{
"data": [
{
"id": "delivery-uuid",
"event": "ticket.created",
"status": "success",
"status_code": 200,
"attempt_count": 1,
"created_at": "2025-01-15T10:00:00.000Z",
"completed_at": "2025-01-15T10:00:01.000Z"
},
{
"id": "delivery-uuid-2",
"event": "message.created",
"status": "failed",
"status_code": 500,
"attempt_count": 5,
"created_at": "2025-01-15T09:00:00.000Z",
"completed_at": "2025-01-15T09:15:00.000Z"
}
],
"meta": {
"pagination": {
"page": 1,
"limit": 20,
"total": 150,
"total_pages": 8
}
}
}
Webhook Payload
Each webhook request includes:
- Name
event- Type
- string
- Description
The event type that triggered the webhook.
- Name
timestamp- Type
- string
- Description
ISO 8601 timestamp of when the event occurred.
- Name
organization_id- Type
- string
- Description
Your organization UUID.
- Name
data- Type
- object
- Description
The event data (varies by event type).
ticket.created payload
{
"event": "ticket.created",
"timestamp": "2025-01-15T10:30:00.000Z",
"organization_id": "org-uuid",
"data": {
"id": "ticket-uuid",
"ticket_number": "42",
"subject": "Help with login",
"status": "OPEN",
"priority": "MEDIUM",
"channel": "API",
"customer": {
"id": "customer-uuid",
"email": "[email protected]",
"name": "John Doe"
},
"assignee": null,
"team": null,
"tags": [],
"created_at": "2025-01-15T10:30:00.000Z",
"updated_at": "2025-01-15T10:30:00.000Z",
"closed_at": null
}
}
Message Event Payload
When a new message is added to a ticket, the payload includes the message details along with ticket context.
message.created payload
{
"event": "message.created",
"timestamp": "2025-01-15T11:00:00.000Z",
"organization_id": "org-uuid",
"data": {
"id": "message-uuid",
"ticket_id": "ticket-uuid",
"ticket_number": "42",
"content": "Thanks for your help!",
"type": "INBOUND",
"author": {
"type": "customer",
"id": "customer-uuid",
"email": "[email protected]",
"name": "John Doe"
},
"created_at": "2025-01-15T11:00:00.000Z"
}
}
Verifying Webhooks
To ensure webhook requests are genuinely from Support Station, each request includes a signature header that you can verify:
X-Webhook-Signature: sha256=abc123...
X-Webhook-Timestamp: 2025-01-15T10:30:00.000Z
X-Webhook-Event: ticket.created
Verify the signature using your webhook secret:
Signature verification
import crypto from 'crypto';
function verifyWebhook(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return `sha256=${expectedSignature}` === signature;
}
// In your webhook handler
app.post('/webhook', (req, res) => {
const signature = req.headers['x-webhook-signature'];
const payload = JSON.stringify(req.body);
if (!verifyWebhook(payload, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
// Process the webhook
const event = req.body;
console.log('Received event:', event.event);
res.status(200).send('OK');
});
Best Practices
- Respond quickly: Return a 2xx response within 5 seconds. Process webhooks asynchronously if needed.
- Handle duplicates: Webhooks may be delivered more than once. Use the delivery ID to deduplicate.
- Verify signatures: Always verify the webhook signature before processing.
- Retry handling: Failed webhooks will be retried with exponential backoff (5 attempts over ~30 minutes).
- Circuit breaker: After 10 consecutive failures, webhooks are automatically disabled. Re-enable via the API or dashboard.