MeetOne retries failed webhook deliveries automatically, so your endpoint needs to handle both retries and the occasional duplicate delivery.
Expected response
Respond within the 30-second timeout with a 2xx status code to acknowledge a delivery.
| Response | Result |
|---|---|
2xx |
Delivery marked as delivered. Not retried. |
4xx |
Delivery marked as failed. Not retried — use this to permanently reject invalid requests. |
5xx |
Delivery marked as failed. Retried with backoff. |
| Timeout (30s) | Delivery marked as failed. Retried with backoff. |
| Network error (DNS failure, connection refused, etc.) | Delivery marked as failed. Retried with backoff. |
| TLS error (e.g. expired certificate) | Delivery marked as failed. Retried with backoff — the issue may resolve within the retry window. |
| Refused destination URL (private/loopback address, or a non-http(s) scheme) | Delivery marked as failed. Not retried. |
Retry policy
Failed deliveries are retried up to 10 times with exponential backoff and jitter. Each retry is scheduled roughly (attempt ** 5) seconds + jitter (30s–10m) after the previous attempt, so retries span from seconds after the first failure up to several hours later for the final attempts. After the 10th failed attempt, the delivery is recorded as permanently failed and is not retried further.
Because retries can span hours, don't assume a delivery you haven't received yet has been abandoned — check the delivery's status in the admin under Webhook Events before concluding it failed for good.
What's never retried
Two categories of failure are treated as permanent and are not retried:
4xxresponses. MeetOne assumes you deliberately rejected the request (bad signature, unrecognized payload, etc.) and won't keep sending it.- Refused destination URLs. If your endpoint's hostname resolves to a private, loopback, link-local, or otherwise non-public address, or the URL isn't
http(s), the delivery is rejected outright as unsafe and not attempted again. This is re-checked at delivery time, not just when you save the endpoint, so a hostname that starts pointing at a private address after the fact will also be blocked.
If you want MeetOne to stop retrying an event you can't process, return a 4xx rather than ignoring the request or timing out.
Using X-Request-ID as an idempotency key
Every delivery carries an X-Request-ID header — a UUID generated once, the first time MeetOne records that delivery. The value stays the same across every retry of that delivery, so it's safe to use as an idempotency key: store the IDs you've already processed, and skip any delivery whose ID you've seen before.
X-Request-ID: 8f14e45f-ceea-467e-b0fd-d0b3f1e6f39c
Duplicate deliveries of the same event can also occur under rare conditions, independent of retries. If you need stronger guarantees than X-Request-ID alone provides, also key off a natural identifier in the payload (e.g. a room token plus event type).
Respond quickly, process asynchronously
Your endpoint should acknowledge a delivery as fast as possible. Do the expensive part of your integration — database writes, calls to other services, notifications — after responding, not before. A handler that blocks on downstream calls risks hitting the 30-second timeout, which MeetOne treats as a failure and retries.
A typical pattern:
- Verify the signature (see Verifying webhook signatures).
- Check
X-Request-IDagainst deliveries you've already processed; skip if seen. - Enqueue the payload for background processing.
- Return
200immediately.
Questions? Contact us at support@meetone.io.