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-createdfromticket-updatedin 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
- 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). - 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. - 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.
| Trigger | Fires when |
|---|---|
ticket-created | A ticket is created |
ticket-updated | A ticket is updated (including tag changes) |
ticket-message-created | A new message is added to a ticket |
ticket-self-unsnoozed | A ticket's snooze delay ends |
ticket-message-failed | A message fails to send |
ticket-assignment-updated | The ticket assignee changes (exclusive: can't be combined with other triggers) |
ticket-status-updated | The ticket status changes (exclusive: can't be combined with other triggers) |
ticket-handed-over | A 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
- references/overview.md — Triggers, template variables, payload design, delivery behavior
- references/setup.md — Creating the HTTP integration in Gorgias (UI and API)
- references/verification.md — Header auth, custom headers, OAuth2, debugging