Webhooks

Get notified when a ShopSniffer report completes — pass a webhook URL when creating a job, and optionally a notification email.

Overview

Instead of polling GET /api/jobs/:id/status, pass a webhook_url when creating a job and ShopSniffer will POST a completion event to your URL as soon as the report is ready. You can also pass notify_email to receive an email notification on completion.

Registering a webhook

Pass webhook_url in the body of POST /api/jobs:

bash
curl -X POST https://shopsniffer.com/api/jobs \ -H "X-API-Key: ss_your_key_here" \ -H "Content-Type: application/json" \ -d '{ "domain": "allbirds.com", "webhook_url": "https://your-server.com/hooks/shopsniffer", "notify_email": "you@example.com" }'

Both fields are optional and independent. You can use one, the other, or both.

Webhook payload

When the job completes, ShopSniffer POSTs this JSON body to your URL:

json
{ "event": "job.completed", "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "domain": "allbirds.com", "slug": "allbirds-com", "report_url": "https://shopsniffer.com/report/a1b2c3d4-e5f6-7890-abcd-ef1234567890", "api_url": "https://shopsniffer.com/api/reports/a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status_url": "https://shopsniffer.com/api/jobs/a1b2c3d4-e5f6-7890-abcd-ef1234567890/status" }

Content-Type is application/json. The only event type today is job.completed. Any 2xx response marks delivery as successful; anything else (including network errors) marks it as failed.

Delivery semantics

Webhooks are delivered exactly once after the job's notify-callbacks workflow step runs. If your endpoint is unreachable or returns a non-2xx status, delivery is marked failed and not retried automatically. Build idempotency and a fallback poll into your integration.

  • One attempt per callback. The workflow step runs once when the job transitions to completed. Status is recorded in the webhook_callbacks table (pendingdelivered | failed) with an attempts counter.
  • No HMAC signing. The request has no signature header. Verify the caller by one of:
    • Using a hard-to-guess secret path (e.g. https://your-server.com/hooks/shopsniffer/<random-token>)
    • Allowlisting the Cloudflare Workers egress IPs on your firewall
    • Cross-checking the job_id against a job you created and persisted locally
  • No custom headers or query params. If you need to pass context (user ID, internal job reference, environment tag), encode it in the webhook URL path or query string when you register it.
  • Ordering. Only one job.completed event per job. If the job is retried (via the admin retry endpoint), a new job ID is created with its own webhook callback.

Fallback: poll as a safety net

Because delivery is single-attempt, pair webhooks with a lightweight status poll for mission-critical integrations:

typescript
// Register webhook at creation const { job } = await createJob({ domain, webhook_url }); // Also set a timer — if no webhook arrives in 10 minutes, poll once setTimeout(async () => { const status = await fetch(`/api/jobs/${job.id}/status`).then(r => r.json()); if (status.status === "completed" && !webhookReceived(job.id)) { handleCompletion(job.id); // reconcile manually } }, 10 * 60 * 1000);

Email notifications

Pass notify_email in the job creation body to have ShopSniffer send a completion email directly. Emails are delivered via the EMAIL Workers binding and link to the report URL. Tracked status: pendingsent | failed (recorded in the email_notifications table).

bash
curl -X POST https://shopsniffer.com/api/jobs \ -H "X-API-Key: ss_your_key_here" \ -H "Content-Type: application/json" \ -d '{"domain": "allbirds.com", "notify_email": "you@example.com"}'

Email delivery is also single-attempt — the same caveats as webhooks apply.

Next steps

Jobs API

Full POST /api/jobs reference including webhook_url and notify_email fields.

Learn More
AI agent integration

Use webhooks to trigger autonomous agent pipelines.

Learn More
Monitor a store

End-to-end guide combining tracking, webhooks, and changelog.

Learn More
Rate limits

Limits for job creation and related endpoints.

Learn More
Ask a question... ⌘I