Stop polling. We push to you.

Subscribe an HTTPS endpoint and Rank Prompt POSTs the moment a report or scheduled run finishes across ChatGPT, Perplexity, Google AI Mode, Claude, Gemini, and Grok. Signed, retried, and replayable, so your dashboards, warehouse, and alerts react in seconds, not on a cron.

HMAC-signed payloads Automatic retries No polling
Webhooks · Live
Incoming delivery http Live
POST /webhooks/rankprompt HTTP/1.1
Host: your-app.com
X-RP-Event: report.completed
X-RP-Event-Id: evt_9b2c7e1f…
X-RP-Signature: t=1751198400,v1=5f1e9c8a2b…
Content-Type: application/json

{
  "id": "evt_9b2c7e1f…",
  "type": "report.completed",
  "api_version": "v1",
  "data": { "report_id": "f4c1…", "brand_id": "a1b2…", "status": "completed" }
}

Signed with HMAC-SHA256 · verified against your secret

How it works

A push, not a poll

Register an endpoint once with the public API and pick the events you care about. When a report or scheduled run reaches a terminal state, we POST a signed JSON envelope to your URL, retrying until it sticks.

The envelope is intentionally small: it carries the event type and the ids you need to GET the full resource from /v1. There’s no in-app toggle, webhooks are managed entirely over the API.

transport
HTTPS POST (public URLs only)
signature
X-RP-Signature · HMAC-SHA256
events
4 types · report & schedule
delivery
at-least-once · retried · replayable
Events

Four events, terminal states only

We emit when work is actually done, completed or failed, for both on-demand reports and scheduled runs. No noisy progress pings.

report.completed

A manual or scheduled report finished analyzing. Carries report_id, brand_id, status, and prompt counts.

report.failed

A report run errored out before completing. Carries report_id, brand_id, and status.

schedule.run.completed

A scheduled batch finished. Carries scheduled_run_id, scheduled_report_id, brand_id, and region counts.

schedule.run.failed

A scheduled batch failed. Includes a failure_reason when one is available.

Quickstart

Live in two steps

Register an endpoint, then verify the signature on every request. That’s the whole integration.

1

Register an endpoint

Create a webhook bash
curl -X POST https://api.rankprompt.com/v1/brands/$BRAND_ID/webhooks \
  -H "Authorization: Bearer $RANKPROMPT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/rankprompt",
    "events": ["report.completed", "schedule.run.completed"],
    "description": "Production listener"
  }'

# 201 Created — the signing secret is shown exactly once, store it now:
# { "id": "whk_…", "secret": "whsec_…", "secret_version": 1, "is_active": true }

The signing secret comes back exactly once, store it now. Need a key first? Mint one on the Developers page.

2

Verify the signature

verify.ts typescript
import crypto from "node:crypto";

// Verify the X-RP-Signature header against the RAW request body.
export function isFromRankPrompt(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const signed = parts.t + "." + rawBody;
  const expected = crypto.createHmac("sha256", secret).update(signed).digest("hex");

  // Constant-time compare against v1 (also accept v0 during a secret rotation).
  const match = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));

  // Reject replays: require a recent timestamp (within 5 minutes).
  const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
  return match && fresh;
}

Always sign over the raw request body, before any JSON parsing, and compare in constant time. During a secret rotation, also check the v0 signature.

Payload

A predictable envelope

Every event ships the same envelope shape. The data block carries the ids; fetch the full resource from /v1 when you need more.

report.completed json
{
  "id": "evt_9b2c7e1f4a8d4c0e9f2b6a1d3c5e7f90",
  "type": "report.completed",
  "api_version": "v1",
  "created_at": "2026-06-29T12:00:00Z",
  "data": {
    "report_id": "f4c1e2a0-1b2c-3d4e-5f60-7a8b9c0d1e2f",
    "brand_id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
    "scheduled_report_id": null,
    "status": "completed",
    "total_prompts_count": 24,
    "ranked_prompts_count": 24
  }
}

Request headers

X-RP-Event
The event type, e.g. report.completed.
X-RP-Event-Id
Stable id for the logical event (evt_…). Dedupe on this.
X-RP-Delivery-Id
Unique id for this individual delivery attempt.
X-RP-Signature
Timestamp + HMAC-SHA256: t=…,v1=… (and v0=… mid-rotation).
Reliability

Built to deliver, and to verify

Retries, auto-disable, idempotency, and signed rotation, so a flaky endpoint never loses you an event and a leaked secret never costs you downtime.

Automatic retries

Failed deliveries retry on a 30s → 2m → 10m → 1h → 6h → 24h backoff: up to seven attempts before a delivery is dropped.

Auto-disable + alert

After 20 consecutive failures we disable the endpoint and email the brand owner. Re-enable it with one PATCH once it’s fixed.

At-least-once delivery

Delivery is at-least-once after success. Dedupe on X-RP-Event-Id and keep handlers idempotent. Per-endpoint order is preserved.

Zero-downtime rotation

Rotate the signing secret anytime. The old secret keeps signing as v0 for 24h, so you roll your verifier with no gap.

Delivery log & replay

Inspect recent attempts (status, response code, error) and replay any past delivery straight from the API.

Public HTTPS only

Endpoints must be public https:// URLs. Private, loopback, and non-routable targets are rejected (SSRF guard).

Plan

Webhooks are included on every Starter plan and up, or on a standalone API plan. It is the same entitlement as the public /v1 API and the MCP server.

See plans

Manage endpoints with the write:webhooks scope; inspect deliveries with read:webhooks.

FAQ

Webhook questions

Everything teams ask before they wire up an endpoint. Email us if your question isn't covered.

How are webhooks different from polling the API?
You stop polling report status from a worker. Rank Prompt POSTs to your endpoint the moment a report or scheduled run reaches a terminal state, so your stack reacts in seconds instead of on a cron.
How do I verify a request really came from Rank Prompt?
Every request carries an X-RP-Signature header of the form t=<timestamp>,v1=<hmac>. Recompute an HMAC-SHA256 of "{timestamp}.{raw body}" with your signing secret and compare it to v1 in constant time. Reject stale timestamps to prevent replays.
What happens if my endpoint is down?
We retry with exponential backoff (30s, 2m, 10m, 1h, 6h, 24h) for up to seven attempts. After 20 consecutive failed deliveries the endpoint auto-disables and we email the brand owner. Fix it, then re-enable with a PATCH.
Can the same event be delivered twice?
Yes. Delivery is at-least-once after success, so design for it: dedupe on the event id (X-RP-Event-Id) and make your handler idempotent. Deliveries to a single endpoint preserve order.
Which events can I subscribe to?
Four: report.completed, report.failed, schedule.run.completed, and schedule.run.failed. You can run up to 5 active endpoints per brand, each subscribing to any subset of events.
What is in the payload?
A small JSON envelope: id (evt_…), type, api_version, created_at, and a data block. The data block carries the ids (report_id, brand_id, …); fetch the full resource from /v1 when you need the detail.
How do I rotate the signing secret?
POST to the endpoint’s secret-rotations route. The new secret is returned once and the old one keeps signing deliveries as v0 for a 24-hour overlap, so you can roll your verifier with zero downtime.
What plan do I need?
Webhooks are included on every Starter plan and up, or on a standalone API plan. It is the same entitlement as the public /v1 API and the MCP server.

Still have questions? Contact our team

Webhooks · Live

7-day free trial · 50 free prompts

Wire Rank Prompt into your stack

Start a free trial, register an endpoint, and let report and schedule events flow straight into your dashboards, warehouse, and alerts.