Delivery & retries
How OnlyFans API sends webhook events to your endpoint, when a delivery is retried, what happens to endpoints that keep failing, and how to inspect or replay past deliveries.
This page describes exactly how we call your endpoint, so you can size your timeouts, make your handler idempotent, and understand what you see in the delivery log.
How we call your endpoint
Every event is sent as a single POST request with a JSON body:
{
"event": "subscriptions.new",
"account_id": "acct_123",
"payload": {
// Event-specific data — see the event catalog
}
}| Header | Value |
|---|---|
Content-Type | application/json |
User-Agent | OnlyFansAPI.com/Webhook-Client |
Signature | HMAC SHA256 of the raw request body — only sent when the webhook has a signing secret |
X-OFAPI-Idempotency-Key | Stable identifier for the event, e.g. evt_9c1f0a4b…. Use it to deduplicate. Not sent for ephemeral events (see below) |
X-OFAPI-Redelivery-Of | Only present on a manual redelivery; contains the delivery ID that was replayed |
Requests may not come from a fixed IP
Outbound webhook requests are routed through our edge network, so source IP addresses are not
stable and cannot be allowlisted. Verify the Signature header instead — see
Protecting your webhooks.
What counts as a successful delivery
A delivery attempt succeeds when your endpoint returns any 2xx status code within our timeouts:
- 5 seconds to establish the TCP/TLS connection
- 10 seconds total for the request, including your response
An attempt is treated as failed when:
- your endpoint returns any non-2xx status code (3xx redirects are not followed as success), or
- the connection or the response exceeds the timeouts above, or
- the connection fails (DNS, TLS, refused connection).
The response body you return is ignored — only the status code matters.
Answer first, process later
Do your processing after you respond. Acknowledge with a 200 as soon as you have persisted
the payload (e.g. onto your own queue). Handlers that do heavy work inline are the single most
common cause of duplicate events, because they blow the 10-second budget and trigger a retry.
Retry schedule
A failed delivery is retried up to 3 attempts in total with exponential backoff:
| Attempt | Sent |
|---|---|
| 1 | Immediately when the event occurs |
| 2 | ~10 seconds after attempt 1 fails |
| 3 | ~100 seconds after attempt 2 fails |
If attempt 3 fails, the delivery is abandoned — we do not retry it again later. The whole retry window spans roughly 2 minutes. Backoff delays are a minimum, not a guarantee: retries run on a separate queue, so a retry can land slightly later than the values above under load.
Two status codes short-circuit the schedule. If your endpoint responds with 404 Not Found or 410 Gone, we treat the endpoint as intentionally removed and stop retrying immediately.
At-least-once delivery
We guarantee at-least-once delivery, not exactly-once. Your endpoint can receive the same event more than once — a retry after a response that timed out on our side but succeeded on yours, a network-level duplicate, or a manual redelivery.
Deduplicate on the X-OFAPI-Idempotency-Key header: it stays identical across every attempt of the
same event, including manual redeliveries. Store the key, and ignore an event you have already
processed.
Ephemeral events such as users.typing,
users.online and
users.offline carry no idempotency key — they are
only meaningful at the moment they fire, so there is nothing to deduplicate against.
Events are also not ordered. Retries and independent queue workers mean a later event can arrive before an earlier one. If ordering matters to your integration, sort on the timestamps inside the payload rather than on arrival order.
Endpoints that keep failing
To stop a broken endpoint from generating endless retry traffic, each webhook has a circuit breaker:
After 20 consecutive failed deliveries (each having exhausted its retries), the endpoint is automatically paused and your team admins receive an email.
The endpoint cools down for 5 minutes. It is then sent a single probe delivery to test whether it has recovered.
If the probe succeeds, deliveries resume immediately and your admins are notified. If it fails, the cooldown doubles — 10, 20, 40 minutes, and so on, up to a maximum of 6 hours — before the next probe.
Events fired while an endpoint is paused are lost
Deliveries are not buffered during a pause. Events that occur while your endpoint is paused are never sent, and they are not available for redelivery afterwards, because no delivery was ever attempted. Backfill that window from the API instead.
You do not have to wait out a cooldown. Once your endpoint is healthy again, disable and re-enable the webhook — in the console, or via the Update Webhook endpoint — which clears the pause and resumes deliveries right away.
Inspecting deliveries
Every attempt is recorded, including intermediate retries, so a delivery that succeeded on its third try appears as three records.
- Console — open the webhook in the Webhooks section to browse recent attempts, their status codes, and errors.
- API — List Webhook Deliveries returns the same
history, newest first, filterable by event, date range and success. Attempts belonging to one delivery
share a
delivery_uuid.
7-day retention
Delivery records are pruned automatically after 7 days. Anything older is no longer available in the console or through the API.
Replaying a delivery
Any recorded delivery can be re-sent with Redeliver Webhook Delivery:
- The stored payload is replayed verbatim, and the original
X-OFAPI-Idempotency-Keyis preserved — so your deduplication logic keeps working. AnX-OFAPI-Redelivery-Ofheader lets you tell a replay apart from a first delivery. - Replays go to the webhook's current URL and are signed with its current signing secret, not the values recorded at the time of the original delivery.
- The redelivery is queued and follows the normal retry schedule above, so the endpoint returns as soon as
it is accepted. Poll the deliveries list and match the returned
redelivery_idagainstdelivery_uuidfor the outcome. - Redelivery is refused with a
409when the webhook is disabled, still cooling down after repeated failures, or already has a recovery probe in flight.
Credits
Each delivery costs the same whether it succeeds on the first attempt or fails on the last: retries are not billed separately, and a delivery is charged once, on its final outcome. Manual redeliveries are billed like organic deliveries. See Credits for the exact rate.
Subscribing to webhooks
Listen to events from your OnlyFans accounts on your webhook endpoint so your integration can automatically process data.
Protecting your webhooks
It is recommended to validate incoming webhook requests to ensure that they originate from OnlyFans API, and not from a malicious actor. You can do this by verifying the `Signature` header in the request.