Skip to content

Receive a Shopify webhook

A complete inbound walkthrough: take Shopify orders/create webhooks, verify them, and fan them out to your API and a queue — losing nothing if your service is down.

What you'll build

Shopify  ──▶  <ingest-domain>/shopify-store/orders  ──▶  ├─ HTTPS  https://api.acme.in/orders
         (acked + buffered <100ms; HMAC verified in processing)  └─ SQS    acme-orders-q

1. Create the endpoint

Use the Shopify preset — it configures HMAC-SHA256 verification and the 200 < 5s response Shopify expects.

bash
curl -X POST https://api.emithook.com/v1/endpoints \
  -H "Authorization: Bearer $EK_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "slug": "shopify-store",
    "path": "/orders",
    "preset": "shopify",
    "destinations": ["dst_acme_https", "dst_acme_sqs"]
  }'
json
// → 201 Created
{
  "id": "ep_01JX9...",
  "url": "https://<ingest-domain>/shopify-store/orders",
  "verification": "hmac-sha256",
  "status": "active"
}

TIP

The URL is live immediately on the shared ingest domain (<ingest-domain>, config-driven) — no DNS. Point Shopify at it under Settings → Notifications → Webhooks.

2. Add the verification secret

Paste the signing secret Shopify shows you so Emithook can verify the X-Shopify-Hmac-Sha256 header in the processing plane:

bash
curl -X PUT https://api.emithook.com/v1/endpoints/ep_01JX9.../secret \
  -H "Authorization: Bearer $EK_KEY" \
  -d '{ "secret": "shpss_..." }'

The edge accepts and durably buffers every request in <100 ms (never dropped); verification then runs in the processing plane. A request that fails verification is quarantined — durable and inspectable, but never delivered (not a 401 at the edge, never silently dropped).

3. What an incoming request looks like

http
POST /shopify-store/orders HTTP/1.1
Host: <ingest-domain>
X-Shopify-Topic: orders/create
X-Shopify-Hmac-Sha256: 9q8Wd...=
Content-Type: application/json

{ "id": 8201, "total_price": "4999.00", "currency": "INR", "email": "buyer@acme.in" }
http
HTTP/1.1 200 OK
{ "received": true }

Emithook acks in under 100 ms, then fans the event out to both destinations independently — each signed, retried, and logged on its own.

4. Confirm delivery

bash
emithook logs tail --endpoint /shopify-store/orders
12:04:31  evt_01JX… orders/create → dst_acme_https   200  142ms  ✓
12:04:31  evt_01JX… orders/create → dst_acme_sqs      enqueued    ✓

If api.acme.in is down, Emithook retries with backoff and parks events behind the circuit breaker — when it recovers, they drain automatically. Nothing is lost.

5. Replay if needed

bash
# replay everything that dead-lettered for this endpoint
emithook replay --dlq --endpoint /shopify-store/orders

See also

Apache-2.0 licensed · a Finnoto product