> **For coding agents and LLMs:** This is one page from the Social Fetch docs (markdown export). For curated orientation and workflow guidance, start with [`/llms.txt`](https://www.socialfetch.dev/llms.txt); for agent onboarding and crawl rules, use [`/agents.txt`](https://www.socialfetch.dev/agents.txt); for the full endpoint list with links to pages like this one, use [`/llms-endpoints.txt`](https://www.socialfetch.dev/llms-endpoints.txt); for one platform's parameters and curls, use [`/llms-{platform}.txt`](https://www.socialfetch.dev/llms-tiktok.txt); use [`/llms.json`](https://www.socialfetch.dev/llms.json) when you need structured JSON for tool registration.

## This page

- **On-site (HTML):** [https://www.socialfetch.dev/docs/monitors/delivery-retries](https://www.socialfetch.dev/docs/monitors/delivery-retries)
- **Markdown (.mdx) URL:** [https://www.socialfetch.dev/docs/monitors/delivery-retries.mdx](https://www.socialfetch.dev/docs/monitors/delivery-retries.mdx)

## API base URL and authentication

- **API origin (from OpenAPI `servers`):** `https://api.socialfetch.dev`
- **Authentication:** send `x-api-key: sfk_...` on `/v1/**` routes unless the operation is explicitly anonymous (check OpenAPI `security`, the [API reference hub](https://www.socialfetch.dev/docs/api.mdx), [`/llms.txt`](https://www.socialfetch.dev/llms.txt), or [`/llms.json`](https://www.socialfetch.dev/llms.json) for each route).
- **OpenAPI JSON:** [https://www.socialfetch.dev/openapi.json](https://www.socialfetch.dev/openapi.json)

## Recommended docs entrypoints (this site)

- [Documentation overview](https://www.socialfetch.dev/docs.mdx) — top-level orientation (markdown).
- [Quickstart](https://www.socialfetch.dev/docs/quickstart.mdx) — authenticate with `x-api-key`, validate auth with `whoami`, and understand the JSON envelope.
- [SDK](https://www.socialfetch.dev/docs/sdk.mdx) — official TypeScript SDK guide, including `SocialFetchClient`, `Result`, and `unwrap()`.
- [SDK reference](https://www.socialfetch.dev/docs/sdk-reference.mdx) — exhaustive SDK method inventory and route mapping for agents, tooling, and power users.
- [Choose the right endpoint](https://www.socialfetch.dev/docs/choose-endpoint.mdx) — task-oriented route selection for smoke tests, profiles, list endpoints, and single-item lookups.
- [Capability matrix](https://www.socialfetch.dev/docs/capability-matrix.mdx) — fast comparison of identifiers, pagination, outcomes, media download, and SDK coverage.
- [Recipes](https://www.socialfetch.dev/docs/recipes.mdx) — copyable workflows (brand monitoring, transcripts, Ad Library, creator scoring, Reddit research) with credit callouts and SDK examples.
- [Integrations](https://www.socialfetch.dev/docs/integrations.mdx) — MCP for AI clients, n8n verified node, Apify Store Actors, SDK, and REST API connection paths.
- [MCP product page](https://www.socialfetch.dev/mcp) — hosted MCP overview, OAuth, Skills install.
- [MCP integration](https://www.socialfetch.dev/docs/integrations/mcp.mdx) — hosted `/mcp` server, OAuth, Cursor/VS Code/Claude install snippets, 162 endpoint tools, plus docs_search/docs_read for implementation help.
- [n8n integration](https://www.socialfetch.dev/docs/integrations/n8n.mdx) — install `n8n-nodes-socialfetch`, credentials, and workflow examples.
- [Apify integration](https://www.socialfetch.dev/docs/integrations/apify.mdx) — Store Actors under @social-fetch, PPE billing, dataset export, and quick start.
- [`/llms-endpoints.txt`](https://www.socialfetch.dev/llms-endpoints.txt) — every documented operation with a direct link to that route's agent-readable markdown page (prefer this over parsing OpenAPI).
- [`/llms-{platform}.txt`](https://www.socialfetch.dev/llms-tiktok.txt) — per-platform endpoint files generated from OpenAPI (parameters, credits, curls).
- [`/agents.txt`](https://www.socialfetch.dev/agents.txt) — agent crawl/onboarding file with capabilities, auth rules, and allowlist.
- [`/llms.json`](https://www.socialfetch.dev/llms.json) — structured machine-readable operation inventory with parameter names, pagination, outcomes, credits, and SDK mapping.
- [API reference hub](https://www.socialfetch.dev/docs/api.mdx) — human-friendly index of operations with links into generated pages.
- [Errors](https://www.socialfetch.dev/docs/errors.mdx) — shared error envelope and HTTP status guidance.
- [Credits](https://www.socialfetch.dev/docs/credits.mdx) — metering, `402`, and planning batch jobs.
- Outcome semantics such as `found`, `not_found`, and `private` are documented in [Errors](https://www.socialfetch.dev/docs/errors.mdx) and on operation pages when present in the OpenAPI contract.

## Markdown docs convention

- Every docs page has a markdown twin: append **`.mdx`** to the docs pathname (for example `/docs/quickstart` → `/docs/quickstart.mdx`).
- Agents that send `Accept: text/markdown` on `/docs/**` HTML URLs may receive markdown directly (same URL, `Vary: Accept`).

---
# Delivery, retries & idempotency (https://www.socialfetch.dev/docs/monitors/delivery-retries)

Webhook delivery is **at-least-once**, not exactly-once. Build your handler assuming any event can arrive more than once.

## Retry ladder

Success is any `2xx`. On anything else (non-2xx, timeout, connection error), the delivery retries on a fixed schedule:

| Attempt | Delay after the initial attempt |
| ------- | ------------------------------- |
| 1       | immediate                       |
| 2       | +30 seconds                     |
| 3       | +2 minutes                      |
| 4       | +10 minutes                     |
| 5       | +30 minutes                     |
| 6       | +2 hours                        |
| 7       | +6 hours                        |
| 8       | +12 hours                       |

Eight attempts over roughly **21 hours**. No ordering guarantee across different events; each is delivered independently.

If attempt 8 still fails, the delivery is marked `failed` and retries stop. After that, only a **manual redelivery** (dashboard Redeliver, or `POST /v1/webhook-deliveries/{id}/redeliver`) sends it again. Manual redeliveries are flagged `manual: true` and show up as a fresh attempt (`attempt` keeps incrementing), so the delivery log is a complete history of every attempt for that event.

## Dedup on event id, not delivery id

Retries and manual redeliveries of the same event carry the **same** `socialfetch-event-id` (and the same `id` in the envelope). That's your dedup key.

```
socialfetch-event-id: evt_01J9…       <- same across every attempt of this event
socialfetch-delivery-id: whd_01J9…    <- unique per attempt; do not use this to dedup
```

```ts
// Swap the Set for a durable store (Redis, a unique DB constraint, etc.) in production.
const processedEventIds = new Set<string>();

async function handleWebhookEvent(event: { id: string; type: string; data: unknown }) {
  if (processedEventIds.has(event.id)) {
    return; // already handled — retry or manual redelivery
  }
  processedEventIds.add(event.id);

  // ... your side effects here, e.g. write a row, send a notification
}
```

In production, a unique constraint on `event_id` in the table your handler writes to is usually enough — let the database reject the duplicate insert.

## Endpoint health & auto-disable

* Any `2xx` resets the endpoint's failure streak.
* **HTTP `410 Gone`** disables the endpoint immediately (stop sending).
* Otherwise, an endpoint auto-disables after **100 consecutive failures** or **3 days** of continuous failure, whichever comes first. Disabling sends an email, posts a status notice to affected monitors, and shows a dashboard banner.

  A disabled endpoint doesn't pause attached monitors. Checks still run, still bill, and still record events — only outbound delivery stops. Events stay queryable through the [pull API](#pull-api-the-backstop). Re-enabling resumes delivery for **new** events; old undelivered events don't replay automatically. Pull them or redeliver manually within the retention window.

## Pull API: the backstop

Events are queryable independent of webhook delivery — useful if you can't host an endpoint, or want a source of truth that doesn't depend on your uptime:

Cursor-paginated, up to 100 per page, within the 30-day retention window. A monitor with no `webhookEndpointId` is a valid **pull-only** monitor: poll the event log instead of receiving pushes.

## Retention

Events and delivery logs (headers, payload, response snippet, timing, attempt number) are retained for **30 days**. Redelivery and the pull API stop working for older events — export anything you need longer.

## Where to go next

- [Receiving & verifying webhooks](/docs/monitors/webhooks) — Verify signatures before you act on any event.

- [Testing webhooks locally](/docs/monitors/testing-locally) — Watch retries and redelivery in the test inbox before you go live.

- [Billing for monitors](/docs/monitors/billing) — Retries don't re-bill — only the original poll charges credits.

- [Webhook deliveries API reference](/docs/api/v1/webhook-endpoints/id/deliveries/get) — Redelivery, delivery log filters, and cursor tailing.