Skip to main content
Reference

Retry Policy

XRNotify guarantees at-least-once delivery. If your endpoint does not return a 2xx status within 10 seconds, the delivery is retried automatically on an exponential backoff schedule.

Overview

Every event detected on the XRPL is delivered to your webhook endpoint at least once. In practice, the vast majority of deliveries succeed on the first attempt. The retry mechanism exists to handle transient failures — network blips, brief endpoint unavailability, or accidental non-2xx responses.

Because retries are a normal part of the delivery guarantee, your webhook handler must be idempotent. Use the X-XRNotify-Delivery-Id header or the deterministic event_id field to detect and safely skip duplicate deliveries.

Retry schedule

AttemptDelay after previousCumulative elapsedNotes
1Immediate0sInitial delivery
21 minute~1mFirst retry
35 minutes~6m
430 minutes~36m
52 hours~2.6h
66 hours~8.6h
712 hours~20.6h
824 hours~44.6hFinal attempt

After 8 failed attempts, the delivery moves to dead status. No further automatic retries occur. You can still trigger a manual retry at any time.

What counts as a failure

A delivery attempt is marked as failed if any of the following occur:

  • HTTP status 3xx, 4xx, or 5xx returned by your endpoint
  • No response received within 10 seconds (connection timeout)
  • SSL/TLS handshake failure or expired certificate
  • DNS resolution failure for your endpoint's hostname
  • Connection refused (e.g., server is down or port not open)

A delivery is considered successful if:

HTTP status 200–299 returned within 10 seconds

Jitter

Each retry delay has ±10% random jitter applied. This prevents a thundering herd scenario where many deliveries that failed simultaneously all retry at exactly the same time, which could overwhelm your endpoint.

# Backoff formula with jitter:
delay(attempt) = base_delay[attempt] × (1 + random(-0.1, 0.1))

# Example — attempt 3 base delay = 5 minutes:
# Actual delay will be between 4m30s and 5m30s

Auto-disable behavior

Each webhook tracks a consecutive_failures counter. This counter increments each time a delivery reaches the final failed state (after all 8 attempts), and resets to zero on any successful delivery.

If consecutive_failures reaches 100, XRNotify automatically sets the webhook status to disabled and sends an email notification to your account's registered email address.

Auto-disable: A disabled webhook stops receiving new events. No events are queued during the disabled period — use the Replay API to recover missed events after re-enabling.

Re-enable a disabled webhook via the dashboard or the API:

curl -X PATCH https://api.xrnotify.io/v1/webhooks/wh_abc123 \
  -H "X-XRNotify-Key: xrn_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "status": "active" }'

Delivery status values

StatusDescription
pendingQueued for initial delivery or awaiting a scheduled retry.
deliveringCurrently being sent to your endpoint.
succeededYour endpoint returned a 2xx status within the timeout.
failedAll retry attempts have been exhausted. Manual action required.
deadAlias for failed — delivery will not be retried automatically.

Manual retry

Even after a delivery reaches failed status, you can trigger an immediate re-attempt:

curl -X POST https://api.xrnotify.io/v1/deliveries/dlv_abc123/retry \
  -H "X-XRNotify-Key: xrn_live_xxx"

The response includes the delivery object with the updated status, response_code, and last_error fields after the attempt completes.

Bulk recovery with Replay

For large-scale recovery — such as when your endpoint was down for several hours and hundreds of deliveries failed — use the Replay API to re-deliver all events matching a time window in one request, rather than retrying them individually.

curl -X POST https://api.xrnotify.io/v1/replay \
  -H "X-XRNotify-Key: xrn_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "webhook_id": "wh_abc123",
    "filters": {
      "since": "2024-01-15T00:00:00Z",
      "until": "2024-01-15T12:00:00Z"
    }
  }'

The Replay API re-delivers events as new deliveries with fresh X-XRNotify-Delivery-Id values. Because the event_id in the body is deterministic and unchanged, you can use it as a stable idempotency key. See the Replay API reference for the full filter options.

Idempotency is required. Because XRNotify retries deliveries, your endpoint may receive the same event more than once. Always implement idempotency using the X-XRNotify-Delivery-Id header or the event_id body field to detect and safely skip duplicate processing.
Secret rotation note: Events are retried against your webhook's current configuration. If you rotate your webhook secret between the original delivery and a retry, the retry will be signed with the new secret — not the original one. Ensure your signature verification uses the current secret stored in your environment.

Next steps