Send it elsewhere
Coming soonPipe every analysis into whatever you already run.
Signed outbound events on every delivery, every watchlist alert, every playbook update. You point us at an HTTPS endpoint. We POST JSON. You build the rest.
Events we emit
Three event types at launch.
analysis.delivered
Fires when a new ranked analysis lands in your dashboard. The payload carries the report id, the top niche verdict, the ranked list size, and the source confidence summary so you can route by tier of evidence.
niche.alert
Fires when a niche on your watchlist shows a positive delta in a fresh report. Rising demand signal, new competitor entry, regulatory shift on the kill condition you logged. One event per niche per delivery.
playbook.updated
Fires when an on demand AI playbook finishes generating, or when a saved playbook is rederived against a fresh analysis. Carries the playbook id and a diff summary so you only sync what changed.
More event types follow once the first three are stable in production. We will version the schema and ship a deprecation window before any breaking change.
Payload shape
A real analysis.delivered body.
Every event is JSON. Envelope fields are stable across event types. The data object varies by event. Timestamps are ISO 8601 UTC. Ids are ULIDs you can sort lexicographically.
{
"id": "evt_01HM4Q6V8R2X9YJZP3T0K1B7AS",
"type": "analysis.delivered",
"created_at": "2026-05-22T14:00:00.000Z",
"tier": "operator",
"data": {
"analysis_id": "rpt_01HM4Q6V8R2X9YJZP3T0K1B7AS",
"delivered_at": "2026-05-22T14:00:00.000Z",
"top_niche": {
"slug": "sworn-translators-spain-maec",
"title": "Sworn translators registered with Spain MAEC",
"verdict": "GO_WITH_CAVEATS",
"score": 78,
"kill_condition": "MAEC fee schedule restructures in 2026 Q4"
},
"ranked_count": 20,
"source_confidence": {
"primary": 14,
"industry": 9,
"media": 4,
"low": 1
},
"dashboard_url": "https://thedetective.io/dashboard/analyses/rpt_01HM4Q6V8R2X9YJZP3T0K1B7AS"
}
}Request headers
POST /webhooks/the-detective HTTP/1.1
Host: your-server.example.com
Content-Type: application/json
User-Agent: TheDetective-Webhooks/1.0
X-Detective-Event: analysis.delivered
X-Detective-Delivery: evt_01HM4Q6V8R2X9YJZP3T0K1B7AS
X-Detective-Timestamp: 1747922400
X-Detective-Signature: t=1747922400,v1=5b9f3c9a8d2e1f7c4b6a2d8e0f1a3b5c7d9e1f2a4b6c8d0e2f4a6b8c0d2e4f6aSignature verification
HMAC SHA256. Verify before you trust.
On setup you receive a secret of the form whsec_followed by 48 random bytes. We sign every request with that secret. The signature header is the concatenated timestamp and request body, HMAC SHA256, hex encoded.
Reject any request with a timestamp more than 5 minutes off yours. Compare signatures with a constant time function. Never log the raw secret.
import crypto from "node:crypto";
export function verify(req: { headers: Record<string, string>; rawBody: string }) {
const header = req.headers["x-detective-signature"] ?? "";
const parts = Object.fromEntries(
header.split(",").map((kv) => kv.split("=") as [string, string])
);
const timestamp = parts.t;
const provided = parts.v1;
// Reject anything older than 5 minutes to block replay.
const skew = Math.abs(Date.now() / 1000 - Number(timestamp));
if (skew > 300) return false;
const signed = `${timestamp}.${req.rawBody}`;
const expected = crypto
.createHmac("sha256", process.env.DETECTIVE_WEBHOOK_SECRET!)
.update(signed)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(provided)
);
}Retry policy
Six attempts. Then we stop and tell you.
We retry on any 5xx response or network timeout with exponential backoff. We do not retry on 4xx because that means your endpoint rejected the payload on purpose. After the last retry we mark the delivery failed and surface it in your dashboard so you can replay it manually.
- 01immediatelyfirst delivery attempt
- 02+30 secondsfirst retry
- 03+2 minutesexponential backoff
- 04+10 minutesbackoff continues
- 05+1 hourbackoff continues
- 06+6 hoursfinal retry, then marked failed
A 2xx response within 10 seconds counts as accepted. If your endpoint needs longer, return 200 immediately and queue the work behind it.
Delivery flow
One event, one POST, one acknowledgment.
01
Event fires
analysis.delivered
02
We sign
HMAC SHA256
03
POST to you
https endpoint
04
You ack
200 within 10s
On 5xx or timeout we retry on the schedule above. On 2xx we mark delivered.
Tier availability
Operator tier.
Webhooks are an Operator feature. Daily analyses, the largest ranked pool, and the volume of niche alerts make a signed feed useful in a way the lower tiers do not need. If you need the feed on Hunter, write to us and we will tell you honestly when we open it up.
Starter
Not included
Explorer
Not included
Hunter
Not included
Operator
Included
Build the integration we did not.
Webhooks ship as part of the Operator tier. Sign up now and we will email you the day the endpoint goes live.