Findable
Reference

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.

eventWhen it fires
article.publishedAn article finished generating. Sent once per article.
webhook.testYou 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.

FieldTypeDescription
eventstringAlways present. article.published or webhook.test.
article_idstringFindable's stable ID for the article. Identical across retries of the same delivery; use it for de-duplication.
titlestringThe article title.
slugstringA 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.
typestringArticle type: roundup, alternatives, comparison, howto, or explainer. If absent, treat it as explainer.
markdownstringThe article body as Markdown. This is the canonical content article.published ships today.
excerptstringA short summary. Sent on test events.
htmlstringReserved for rendered HTML. Not populated yet, so it is absent today.
tagsarray of stringsReserved. Not populated yet, so it is absent today.
generated_atstringAlways present. RFC 3339 timestamp in UTC, e.g. 2026-06-07T14:21:09Z.

Example: article.published

{
  "event": "article.published",
  "article_id": "art_8fK2pQ7mZ1",
  "title": "Best AI visibility tools for B2B SaaS",
  "slug": "best-ai-visibility-tools-for-b2b-saas",
  "type": "roundup",
  "markdown": "# Best AI visibility tools for B2B SaaS\n\nWhen buyers ask an AI assistant...",
  "generated_at": "2026-06-07T14:21:09Z"
}

Example: webhook.test

{
  "event": "webhook.test",
  "title": "Findable webhook test",
  "excerpt": "If you're seeing this, your webhook is wired up correctly.",
  "generated_at": "2026-06-07T14:21:09Z"
}

Headers

Every request carries:

Content-Type: application/json
User-Agent: Findable-Webhook/1.0
X-Findable-Event: article.published
X-Findable-Signature: sha256=<hmac>
X-Findable-Attempt: 1

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=.

import crypto from "node:crypto";
 
function verify(rawBody, header, secret) {
  const expected =
    "sha256=" +
    crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(header), Buffer.from(expected));
}

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.

On this page