Webhooks
Get events delivered to any HTTPS endpoint the moment they happen. Works with Zapier, n8n, IFTTT, and Make, or your own code.
Webhooks send events to your endpoint as they happen: new articles, saved and unsaved items, new episodes, and arriving newsletters. Point one at a Zapier or n8n hook, or receive and verify the events in your own code.
Create and manage webhooks under Automation → Webhooks. You can hold up to 10 at a time, each with its own endpoint, signing secret, and event selection.
Events
| Event | Fires when |
|---|---|
article.new | New articles appear in a feed you subscribe to |
article.starred | You save an item |
article.unstarred | You unsave an item |
subscription.added | You subscribe to a feed or newsletter |
subscription.removed | You unsubscribe (including OPML rollbacks) |
episode.new | New episodes appear in a podcast you subscribe to |
newsletter.new | A newsletter you've connected arrives |
You choose the events each webhook receives. Article feeds fire article.new, podcast feeds fire episode.new.
Envelope
Each delivery is a POST with a JSON body and these headers:
| Header | Value |
|---|---|
webhook-id | msg_<delivery id>, the same across retries. Use it to drop duplicates |
webhook-timestamp | Unix seconds |
webhook-signature | v1,<base64> HMAC-SHA256 signature. See Verification |
webhook-event | The event type |
{
"event_type": "article.new",
"data": {
"feed_id": "00000000-0000-0000-0000-000000000001",
"feed_title": "Example Feed",
"count": 1,
"last_update": "2026-01-15T09:30:00+00:00",
"articles": [
{
"article_id": "00000000-0000-0000-0000-000000000002",
"title": "Example article",
"url": "https://example.com/example-article",
"author": "Example Author",
"published_at": "2026-01-15T09:30:00+00:00"
}
]
}
}article.new and episode.new arrive as batches. count is the total number of new entries, and the inline list is capped at 25. When count is larger than the list, fetch the rest with the API.
article.starred / article.unstarred
Both directions share one shape. item_id matches the id used by the items API, while article_id and episode_id identify the underlying article or episode.
{
"item_id": "00000000-0000-0000-0000-000000000004",
"article_id": "00000000-0000-0000-0000-000000000002",
"episode_id": null,
"item_type": "article",
"title": "Example article",
"url": "https://example.com/example-article",
"author": "Example Author",
"published_at": "2026-01-15T09:30:00+00:00",
"feed_title": "Example Feed"
}For episodes, url is the audio enclosure and episode_id is set instead of article_id. feed_title is null when the article reaches you through multiple subscribed feeds.
episode.new
{
"feed_id": "00000000-0000-0000-0000-000000000001",
"feed_title": "Example Podcast",
"count": 1,
"last_update": "2026-01-15T09:30:00+00:00",
"episodes": [
{
"episode_id": "00000000-0000-0000-0000-000000000003",
"title": "Example episode",
"audio_url": "https://example.com/example-episode.mp3",
"duration_seconds": 1800,
"published_at": "2026-01-15T09:30:00+00:00"
}
]
}newsletter.new
One event per received email, listing every article the email contained.
{
"subscription_id": "00000000-0000-0000-0000-000000000005",
"feed_id": "00000000-0000-0000-0000-000000000001",
"feed_title": "Example Newsletter",
"from_email": "sender@example.com",
"subject": "Example Newsletter #12",
"email_id": "00000000-0000-0000-0000-000000000006",
"count": 1,
"articles": [
{
"article_id": "00000000-0000-0000-0000-000000000002",
"title": "Example article",
"url": "https://example.com/example-article",
"author": "Example Author",
"published_at": "2026-01-15T09:30:00+00:00"
}
]
}subscription.added / subscription.removed
{
"subscription_id": "00000000-0000-0000-0000-000000000005",
"feed_url": "https://example.com/feed.xml",
"feed_title": "Example Feed",
"action": "created",
"folder_id": null
}For added events, action is created, existing, or moved. For removed events it is unsubscribe or opml_rollback. Importing an OPML file fires one subscription.added per feed, and rolling the import back fires one subscription.removed per feed.
Verification
Signatures follow the Standard Webhooks spec, so any off-the-shelf verifier works. The signature is HMAC-SHA256 over msg_id.timestamp.body, where body is the exact raw bytes you received. It is base64-encoded and keyed with the signing secret shown once, when the webhook is created.
from standardwebhooks import Webhook, WebhookVerificationError
wh = Webhook("whsec_...") # your signing secret
try:
wh.verify(
payload, # raw request body bytes
{
"webhook-id": headers["webhook-id"],
"webhook-timestamp": headers["webhook-timestamp"],
"webhook-signature": headers["webhook-signature"],
},
)
except WebhookVerificationError:
... # invalid signatureEndpoints must use HTTPS. The secret is shown once at creation. To rotate it, delete and recreate the webhook.
Delivery semantics
- At-least-once. Retries reuse the same
webhook-id, so treat it as your deduplication key. - Retries. Timeouts, 5xx, and 429 responses retry up to 3 times, with a 10 second timeout per attempt. Any other 4xx fails immediately.
- Auto-disable. After 10 consecutive failed deliveries the webhook is disabled and you are emailed. Resuming it resets the failure counter, and so does any successful delivery.
- Event log. The webhook's detail page keeps a rolling 30 day log of deliveries, with payloads and response codes.
- Pause. Pausing stops deliveries without deleting the webhook. Test events still work while paused.
Ordering and bursts
Events across different feeds carry no ordering guarantees. Subscribing to many feeds at once, such as an OPML import, fires subscription.added per feed in quick succession. Feeds you pause stop firing article and episode events until resumed.
Test events
Use Send test event on a webhook to deliver a sample to your endpoint right away. The default is a generic test event. You can also send a sample shaped exactly like a real delivery for any event type. Samples carry an extra "test": true field so your handler can tell them apart from real traffic. Test sends share a 10 per minute limit with delivery resends.
How is this guide?