Hydra is now in beta|Get started free|Follow our journey on X.com

Webhooks Guide
On this page

Webhooks Guide

Webhooks let your application receive real-time HTTP notifications when events occur in your project — orders placed, inventory updated, customers created, and more.

How webhooks work

  1. You register an endpoint URL and choose which event types to subscribe to.
  2. When a matching event occurs, the API sends a POST request to your endpoint with a JSON payload.
  3. Your endpoint processes the payload and returns a 2xx status to acknowledge receipt.

Creating a webhook

curl -X POST https://api.hydrajs.dev/v1/webhooks \
  -H "Authorization: Bearer sk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/webhooks/hydra",
    "events": ["order.created", "order.paid"]
  }'

The response includes a secret field — this is your signing secret, shown once. Store it securely. You’ll use it to verify webhook signatures.

{
	"data": {
		"id": "wh_abc123def456ghij",
		"url": "https://example.com/webhooks/hydra",
		"events": ["order.created", "order.paid"],
		"secret": "whsec_abc123...",
		"active": true,
		"created_at": "2026-08-24T10:00:00.000Z"
	}
}

Payload format

Each delivery sends a JSON body with the event type and the resource data:

{
	"type": "order.created",
	"data": {
		"id": "ord_abc123def456ghij",
		"status": "pending",
		"total": 4999,
		"currency": "USD"
	}
}

Verifying signatures

Every webhook delivery includes an X-Hydra-Signature header containing an HMAC-SHA256 hex digest of the request body, signed with your webhook secret.

Always verify this signature before processing the payload:

import { createHmac } from 'crypto';

function verifyWebhook(body: string, signature: string, secret: string): boolean {
	const expected = createHmac('sha256', secret)
		.update(body)
		.digest('hex');
	return expected === signature;
}

// In your webhook handler
app.post('/webhooks/hydra', (req, res) => {
	const body = req.rawBody; // must be the raw string, not parsed JSON
	const signature = req.headers['x-hydra-signature'];

	if (!verifyWebhook(body, signature, process.env.WEBHOOK_SECRET)) {
		return res.status(401).send('Invalid signature');
	}

	const event = JSON.parse(body);
	// Process the event...
	res.status(200).send('OK');
});

Use the raw body

Signature verification requires the raw request body as a string. If your framework parses JSON automatically, configure it to preserve the raw body. Re-serializing parsed JSON may change whitespace or key order, causing verification to fail.

Retry policy

If your endpoint returns a non-2xx status or doesn’t respond within 10 seconds, the delivery is marked as failed and retried with exponential backoff:

Attempt Delay
1 Immediate
2 5 minutes
3 30 minutes
4 2 hours
5 8 hours

After 5 failed attempts, the delivery is abandoned. Failed deliveries are retained for 7 days; successful deliveries for 30 days. You can inspect delivery history via the API.

Available event types

Products

  • product.created — A product was created
  • product.updated — A product was updated
  • product.deleted — A product was deleted

Orders

  • order.created — An order was placed
  • order.paid — Payment was captured
  • order.fulfilled — All items shipped
  • order.cancelled — The order was cancelled
  • order.refunded — A refund was issued

Customers

  • customer.created — A customer account was created
  • customer.updated — Customer details were updated

Fulfillment

  • fulfillment_order.created — A fulfillment order was created
  • fulfillment.created — A fulfillment was created (items shipped)
  • fulfillment.updated — Tracking or status updated
  • fulfillment.cancelled — A fulfillment was cancelled

Inventory

  • inventory.low — Stock fell below the low-stock threshold

Discounts

  • discount.created — A discount code was created
  • discount.updated — A discount was updated
  • discount.deleted — A discount was deleted

Shipping

  • shipping.zone.created — A shipping zone was created
  • shipping.zone.updated — A shipping zone was updated
  • shipping.zone.deleted — A shipping zone was deleted

Promotions

  • promotion.created — A promotion was created
  • promotion.updated — A promotion was updated
  • promotion.deleted — A promotion was deleted

Draft orders

  • draft_order.created — A draft order was created
  • draft_order.updated — A draft order was updated
  • draft_order.completed — A draft order was converted to an order
  • draft_order.deleted — A draft order was deleted

Companies

  • company.created — A company was created
  • company.updated — A company was updated
  • company.deleted — A company was deleted

Purchase orders

  • purchase_order.created — A purchase order was created
  • purchase_order.updated — A purchase order was updated
  • purchase_order.received — Inventory was received
  • purchase_order.cancelled — A purchase order was cancelled

Returns & refunds

  • refund.created — A refund was initiated
  • refund.succeeded — A refund was processed successfully
  • refund.failed — A refund failed
  • return.requested — A return was requested
  • return.approved — A return was approved
  • return.received — Returned items were received
  • return.rejected — A return was rejected
  • return.cancelled — A return was cancelled
  • return.closed — A return was closed
  • navigation.created — A navigation menu was created
  • navigation.updated — A navigation menu was updated
  • navigation.deleted — A navigation menu was deleted

Store credit

  • store_credit.issued — Store credit was issued to a customer
  • store_credit.used — Store credit was applied to an order
  • store_credit.expired — Store credit expired

Usage

  • usage.warning — Monthly API quota hit 80%, 90%, or 100%

Best practices

  • Respond quickly. Return a 2xx within a few seconds. If processing takes longer, queue the work and acknowledge immediately.
  • Handle duplicates. In rare cases (network timeouts, retries), you may receive the same event twice. Use the event data to make your handler idempotent.
  • Use HTTPS. Webhook URLs must use https:// in production.
  • Verify signatures. Always validate the X-Hydra-Signature header before trusting the payload.
  • Monitor deliveries. Use GET /v1/webhooks/{id}/deliveries to check for failed deliveries and diagnose issues.