Webhooks

Webhooks

Webhooks let Tixallo push events to your own services as tickets and messages move through your workspace, instead of you polling the API.

What webhooks are

A webhook is an HTTPS endpoint you operate that Tixallo POSTs a JSON body to whenever an event happens in your workspace. They're how you keep external systems in sync without polling.

Tixallo's webhook dispatcher runs server-side: when a relevant event fires, every active endpoint that has subscribed to it receives a signed POST.

Configuration is in the app

Webhook endpoints (URL, secret, subscribed events, active flag) are managed inside the Tixallo app. There is no public CRUD API for webhook endpoints in v1 — that surface is app-managed today and a public management API is planned.

Common use cases

  • Send new tickets to a Slack channel.
  • Trigger internal workflows or runbooks when a ticket opens.
  • Sync ticket updates back into your own product.
  • Notify an external CRM when a customer interacts.
  • Feed a data warehouse or automation platform (n8n, Zapier).

Events dispatched by Tixallo

The dispatcher currently emits the following event types. The actual event string sent on the wire is in the event_type field of the payload (see below).

  • ticket.created — fired when a new ticket is created (including via the API).
  • ticket.updated — supported by the dispatcher; fired from internal flows that change a ticket.
  • ticket.closed — supported by the dispatcher.
  • ticket.message.created — fired when a new public message is appended to a ticket.
  • customer.createdplanned. Not currently emitted by the dispatcher.

Payload shape (live)

Tixallo sends a flat JSON object. Every payload includes event_type and created_at; the remaining fields are merged in at the top level rather than nested under data.

{
  "event_type": "ticket.created",
  "created_at": "2026-05-04T10:30:00Z",
  "ticket_id": "9f6c1a3e-2b8d-4e7f-9a1c-d4b2e6c8a1b3",
  "ticket_number": 1043,
  "subject": "Webhook delivery delayed",
  "status": "new",
  "priority": "high",
  "customer": {
    "name": "Alex Example",
    "email": "alex@example.com",
    "company": null
  }
}

Payload shape (planned, richer envelope)

A future revision is likely to nest event-specific fields under a data key and rename event_type to event. If you're writing a new handler, abstract the payload parsing so you can switch envelopes without rewriting your business logic.

{
  "event": "ticket.created",
  "created_at": "2026-05-04T10:30:00Z",
  "data": {
    "ticket_id": "ticket_123",
    "subject": "Unable to log in",
    "status": "open",
    "priority": "normal",
    "customer": { "email": "customer@example.com" }
  }
}

Request headers

Every delivery includes:

  • Content-Type: application/json
  • X-Tixallo-Event — the event type, e.g. ticket.created.
  • X-Tixallo-Signature — HMAC-SHA256 of the raw request body, hex-encoded, using your endpoint's secret.
  • X-Tixallo-Signature-V1 — same value, prefixed v1=, plus X-Tixallo-Signature-Version: v1. Use these for forward-compatible signature verification.

Verifying the signature (Node.js)

import { createHmac, timingSafeEqual } from "node:crypto";

export function verifyTixalloSignature(rawBody, signatureHeader, secret) {
  if (!signatureHeader) return false;
  const expected = createHmac("sha256", secret).update(rawBody).digest("hex");
  // Use the V1 header if present, falling back to the legacy header.
  const provided = signatureHeader.startsWith("v1=")
    ? signatureHeader.slice(3)
    : signatureHeader;
  if (provided.length !== expected.length) return false;
  return timingSafeEqual(Buffer.from(provided), Buffer.from(expected));
}

Handler best practices

  • Use HTTPS. Tixallo will only POST to https:// endpoints in production.
  • Respond fast. Acknowledge with a 2xx within a few seconds. Long work belongs in a queue.
  • Process asynchronously. Push the payload onto a queue and do the heavy lifting in a worker.
  • Log event IDs and bodies. You'll need them when debugging missing or duplicated events.
  • Be idempotent. Tixallo retries on failure, so the same event may arrive more than once. Key on ticket_id + event_type + the event timestamp.
  • Verify signatures. Reject any request whose X-Tixallo-Signature does not match an HMAC-SHA256 of the raw body using your endpoint's secret.

Retries

A delivery is considered successful when your endpoint returns a 2xx status within 8 seconds. Failures (timeouts, connection errors, 4xx/5xx responses) are retried up to three times with backoff:

  • 1 minute after the first failure
  • 5 minutes after the second failure
  • 30 minutes after the third failure

After the final attempt the delivery is marked as a final failure and is no longer retried automatically. Workspace admins can resend any delivery on demand from the Tixallo app.