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: success or failed (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.


GET/api/v1/webhooks

List all webhooks

Returns a list of all webhooks in your organization.

Required scope: webhooks:read

Request

GET
/api/v1/webhooks
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"
    }
  ]
}

GET/api/v1/webhooks/:id

Retrieve a webhook

Returns a single webhook by ID.

Required scope: webhooks:read

Request

GET
/api/v1/webhooks/:id
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"
  }
}

POST/api/v1/webhooks

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

POST
/api/v1/webhooks
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"
  }
}

PATCH/api/v1/webhooks/:id

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

PATCH
/api/v1/webhooks/:id
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/api/v1/webhooks/:id

Delete a webhook

Deletes a webhook. This will stop all event deliveries to this endpoint.

Required scope: webhooks:write

Request

DELETE
/api/v1/webhooks/:id
curl -X DELETE https://api.supportstation.io/api/v1/webhooks/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer {token}"

Response

{
  "data": {
    "deleted": true
  }
}

GET/api/v1/webhooks/:id/deliveries

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

GET
/api/v1/webhooks/:id/deliveries
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.

Was this page helpful?