Agent skill

Gorgias Webhooks Skill

Receive and authenticate Gorgias HTTP integration webhooks. Use when setting up a Gorgias webhook handler for ticket events (ticket-created, ticket-updated, ticket-message-created, ticket-status-updated and other triggers), when building the user-defined request body template with variables like {{ticket.id}}, or when debugging the shared-secret header check. Gorgias does not sign HTTP integration requests: there is no signature header or HMAC, and the request body does not say which trigger fired unless you put the event name in the template yourself.

Install this skill

npx skills add hookdeck/webhook-skills --skill gorgias-webhooks


Gorgias is an e-commerce helpdesk. Its outbound webhooks are HTTP integrations (Settings → Account → HTTP integration): when a ticket event fires, Gorgias calls your URL with the method, headers and body template you configured.

When to Use This Skill

  • How do I receive Gorgias webhooks for ticket events?
  • How do I verify / authenticate a Gorgias HTTP integration request?
  • How do I tell ticket-created from ticket-updated in my webhook handler?
  • What should my Gorgias request body template look like?
  • Why does my Gorgias integration keep timing out or get disabled?

How Gorgias Differs From Signed Webhooks

  1. No signature. Gorgias doesn't sign HTTP integration requests. There are two authentication options: header-based (you add a header such as Authorization: Bearer <secret>; Gorgias sends it as-is) or OAuth2 (Gorgias fetches a token from your token URL with a client ID and secret, then sends it in a header or query string).
  2. You write the payload. The body is a template you configure, filled with Gorgias variables like {{ticket.id}}. Gorgias adds no envelope, no event name and no delivery ID.
  3. The trigger isn't in the request. One integration can listen to several triggers, and nothing in the request says which one fired. Create one integration per trigger and hard-code the name in the body ("event": "ticket-created"). The examples dispatch on that field.

Verification (core)

Header-based auth: compare the whole header value with the value you configured, in constant time.

const crypto = require('crypto');

// Gorgias integration header: Authorization: Bearer <GORGIAS_WEBHOOK_SECRET>
function verifyGorgiasAuthorization(header, secret) {
  if (!header || !secret) return false;                 // fail closed
  const a = Buffer.from(header, 'utf8');                 // the WHOLE header value
  const b = Buffer.from(`Bearer ${secret}`, 'utf8');
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}
import hmac

def verify_gorgias_authorization(header: str | None, secret: str) -> bool:
    if not header or not secret:
        return False
    return hmac.compare_digest(header.encode(), f"Bearer {secret}".encode())

For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.

There is no Gorgias SDK for this, so every example does the compare directly. For a custom header (e.g. X-Gorgias-Secret: <secret>) or OAuth2, see references/verification.md.

Triggers (Event Types)

These are the trigger keys from the Gorgias Integration API (the UI shows them as "Ticket created", etc.). Use the same strings as your event value.

TriggerFires when
ticket-createdA ticket is created
ticket-updatedA ticket is updated (including tag changes)
ticket-message-createdA new message is added to a ticket
ticket-self-unsnoozedA ticket's snooze delay ends
ticket-message-failedA message fails to send
ticket-assignment-updatedThe ticket assignee changes (exclusive: can't be combined with other triggers)
ticket-status-updatedThe ticket status changes (exclusive: can't be combined with other triggers)
ticket-handed-overA ticket is handed over (API only; needs further configuration)

Recommended body template (application/json, one integration per trigger):

{
  "event": "ticket-created",
  "ticket_id": "{{ticket.id}}",
  "subject": "{{ticket.subject}}",
  "status": "{{ticket.status}}",
  "channel": "{{ticket.channel}}",
  "customer_email": "{{ticket.customer.email}}",
  "assignee_email": "{{ticket.assignee_user.email}}",
  "updated_datetime": "{{ticket.updated_datetime}}",
  "message_text": "{{ticket.messages[-1].body_text}}"
}

The examples accept the same keys as application/x-www-form-urlencoded, and the POST, PUT, PATCH and DELETE methods. See references/overview.md for variables.

Delivery Behavior

  • 5-second timeout. Respond fast; queue slow work.
  • Retries: up to 3 times (10s, 20s, 40s) when the endpoint can't be reached. Timeouts are retried only for OAuth2 integrations. Error responses (4xx/5xx) are never retried, in either mode.
  • Auto-disable after 500 consecutive failures. A success resets the count.
  • No delivery ID: dedupe on event + ticket_id + updated_datetime.

Environment Variables

# The secret in your Gorgias integration header: Authorization: Bearer <secret>
GORGIAS_WEBHOOK_SECRET=your_shared_secret

With it unset, the examples return 500 instead of accepting unauthenticated requests.

Local Development

npx hookdeck-cli listen 3000 gorgias --path /webhooks/gorgias

No account required. The CLI gives you a public HTTPS URL to paste into the Gorgias integration's URL field, plus a web UI for inspecting requests. Use port 8000 for the FastAPI example.

Reference Materials


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Oct 28, 2026

View on GitHub →