Webhook payload
The exact JSON Findable POSTs to your webhook, the headers it carries, and how to verify and de-duplicate it.
Findable POSTs a signed JSON body to your configured webhook URL whenever an article finishes generating, and when you click "Send test event". See Publishing with a webhook for setup. This page is the reference for the request itself.
Event types
Every payload carries an event field, and the same value in the
X-Findable-Event header, so you can route without parsing the body.
event | When it fires |
|---|---|
article.published | An article finished generating. Sent once per article. |
webhook.test | You clicked "Send test event" in Settings. |
Payload body
All fields are JSON. Empty fields are omitted from the body entirely, so a real request only contains the keys listed for its event below.
| Field | Type | Description |
|---|---|---|
event | string | Always present. article.published or webhook.test. |
article_id | string | Findable's stable ID for the article. Identical across retries of the same delivery; use it for de-duplication. |
title | string | The article title. |
slug | string | A URL-safe slug derived from the title (lowercase, alphanumeric and hyphens, capped at 80 chars). Use it as your post slug or compute your own from title. |
type | string | Article type: roundup, alternatives, comparison, howto, or explainer. If absent, treat it as explainer. |
markdown | string | The article body as Markdown. This is the canonical content article.published ships today. |
excerpt | string | A short summary. Sent on test events. |
html | string | Reserved for rendered HTML. Not populated yet, so it is absent today. |
tags | array of strings | Reserved. Not populated yet, so it is absent today. |
generated_at | string | Always present. RFC 3339 timestamp in UTC, e.g. 2026-06-07T14:21:09Z. |
Example: article.published
Example: webhook.test
Headers
Every request carries:
X-Findable-Event mirrors the body's event. X-Findable-Attempt is the
delivery attempt number, starting at 1 (see Delivery and retries below).
Verifying the signature
The signature is an HMAC-SHA256 of the raw request body, keyed with your
per-account signing secret (Settings, Publishing, "Signing secret"). To verify,
compute the same HMAC over the raw body and compare it, in constant time,
against the hex after sha256=.
Verify against the raw bytes, before any JSON parsing or re-serialization, or the hash will not match. Most receivers (such as a Zapier Catch Hook) skip verification and trust the URL. Verify only if you run a custom receiver and want defense against URL leakage. Rotating the secret (Settings, Publishing) invalidates the old one immediately, so update your receiver before the next delivery.
Delivery and retries
article.published is delivered asynchronously. Findable makes up to four
attempts: the first immediately, then retries after 1 minute, 5 minutes, and 30
minutes. A 2xx response stops the sequence. A 4xx (other than 429) is
treated as a configuration problem and is not retried; 429 and 5xx are
retried. Each attempt times out after 15 seconds.
Because of retries, your receiver should be idempotent: the same article_id
can arrive more than once, for example if you return 2xx slowly and Findable
times out, then retries. De-duplicate on article_id.
Test events are different: "Send test event" delivers once, synchronously, with no retry, and shows the result (status code and a response excerpt) inline and in Recent deliveries.