Webhooks and rate limits

Which platforms push events and how they are verified, which must be polled, published rate limits with dates, and a sync schedule and poller design.

66 of the 221 platforms in this section push events. 152 must be polled. Three are partial, meaning they push some object types and not others. This page gives the split, the verification method for each push platform, the published limits with the date they were read, and a poller design that survives the mixture.

Read this with Listing and inventory updates for the write direction and the unified data model for what the events populate.

Platforms that push

Grouped by how you prove the request came from the platform, which is the part most often got wrong.

HMAC signature over the request body

The only genuinely safe group. Compute the digest over the raw body with a shared secret and compare in constant time.

Shopify (HMAC SHA-256, X-Shopify-Hmac-Sha256), Shopify POS, BigCommerce, WooCommerce, Wix, Etsy, eBay (Notification API with signature verification), TikTok Shop, Shopee, Lazada, Daraz, Zoho Books, Xero, QuickBooks, EasyPost, ShipStation, GoKwik (Return Prime) and Knot (Knot-Signature).

Warning

Verify against the raw bytes, before any JSON parsing or re-serialisation. A body that is parsed and re-encoded will not match the digest, and the usual workaround, disabling verification, turns the endpoint into an open write path for anyone who learns the URL.

Queue or cloud delivery rather than HTTP

Amazon and Amazon MCF deliver through the Notifications API to SQS or EventBridge. Authenticity comes from the queue's own access control, so there is no signature to check. This is the most reliable delivery in the whole section: the queue absorbs downstream outages.

Snapdeal pushes through Amazon SNS. Magento uses Adobe I/O Events on Adobe Commerce.

Authenticated, but the platform authenticates to you

The platform calls your endpoint with basic auth or an API key that you issue. There is no signature over the body, so the credential is the only control.

Logistiex (basic auth or an API key, explicitly no HMAC), SharkShip, ClickPost, Shipway, NimbusPost, Shiprocket, Delhivery, Zippyy, Pidge, Zippee, Pico Xpress, FyndTMS and UPS (Track Alert).

Treat these endpoints as untrusted input regardless. Rate limit them, validate the shape, and never let an event body drive a write without re-reading from the API.

Unverified push

Some platforms push with no authentication mechanism at all. Odoo is the clearest case: its webhook action is send and forget, with a one second timeout, no retry and no signature. Verified in its own source. Treat an Odoo webhook strictly as a hint to re-read, never as a fact.

Platforms that must be polled

152 platforms, but they are not all the same problem.

  • Rich APIs with no push. FedEx is the notable one: its tracking notification endpoint sounds like a subscription but only sends email, to a maximum of four recipients. Walmart feed status must be polled. RapidShyp, FShip and most Indian carriers are the same.
  • A changed record feed instead of events. iThink Logistics publishes a thirty minute changed AWB feed. This is better than polling every shipment and worse than a webhook; treat it as a queue of identifiers to re-read.
  • No API at all. The 88 platforms with no credential model. "Polling" here means a document pipeline: an email attachment, a portal download or an SFTP drop. The failure signal is silence, so these need an expected arrival window and an alert when nothing arrives.
Note

Business Central's sales order entity has no filterable last modified timestamp, and neither does Dynamics Finance and Supply Chain's SalesOrderHeadersV2. Incremental polling by date is impossible there; use the platform's change tracking or business events instead. This is documented on Microsoft Dynamics.

Published rate limits

All figures read on the date shown and subject to change. Always prefer the platform's own response headers over this table.

Warning

DHL's starting quota of 250 calls per day at one call per five seconds makes the Push API mandatory rather than optional for any real shipment volume. A polling design will exhaust the day's quota within an hour.

Frappe and ERPNext are the interesting exception: because the limiter meters time rather than requests, a narrow query costs less than a broad one. Optimising the query shape matters more than spacing the calls.

A sync schedule by platform class

Derived from the limits above and from what each object actually needs.

For vendor purchase order platforms the schedule is different: check the document source on the agreed cadence, usually daily, and alert on absence rather than on change.

Backoff rules

  1. On a 429, honour Retry-After when present. When absent, back off exponentially from one second with full jitter, capped at five minutes.
  2. On a 5xx, retry up to three times with jitter, then park the item and move on. A platform in a bad state should not consume the whole worker budget.
  3. Never retry a 4xx other than 429 and 408. These are our bug, and retrying turns a visible error into a silent loop.
  4. Treat a signature or clock failure as non retryable until the clock is checked.
  5. Some platforms return failure inside HTTP 200. Tekipost returns success: false with a 200, and Aramex reports HasErrors: true at two nesting levels inside a 200. Parse the body for outcome, never the status code alone.

Designing the poller so one channel cannot starve another

The requirement is that a large seller on a slow channel does not delay a small seller on a fast one.

  • One scheduler, many per channel workers. Each channel + channel_account_id pair gets its own concurrency budget and its own token bucket matching that platform's published limit. A channel that is throttled blocks only its own bucket.
  • Cap concurrency per channel, not globally. An earlier incident on this system had a retrieval process open roughly forty parallel document reads and starve the web tier. The fix was a per lane concurrency cap, and the same principle applies here.
  • Work in bounded slices. A full catalogue resync is split into pages that are enqueued, not held in one long running job. A job that runs for an hour cannot be paused, cannot be rebalanced, and loses everything when it dies.
  • Separate the fast and slow lanes. Order polling and settlement report downloads should not share a worker pool. Settlement files are large and slow; orders are small and latency sensitive.
  • Make the queue age the primary metric. Requests per second tells you how hard you are pushing. Queue age per channel tells you whether anyone is waiting, which is the thing that actually matters.
  • Degrade deliberately. When a channel is throttled for an extended period, drop to orders only and suspend listing reconciliation for that channel rather than letting everything slow equally. Orders are the object with commercial urgency.

Delivery guarantees worth remembering

  • Webhook delivery is at least once everywhere it is documented. Handle duplicates by making event processing idempotent on the platform's event id.
  • Events arrive out of order. Always compare the event's own timestamp against the row's updated_at and discard older ones rather than applying blindly.
  • Commerce7 permanently disables a webhook after 48 hours of errors with no automatic re-enable, so a long outage requires a manual step to recover. Alert on webhook error rate, not only on receipt.
  • An event is a notification, not a record. For anything that affects money or stock, re-read the object from the API before acting on it.