Radar signed webhooks
Push AI provider changes into the system that acts on them
Radar posts the same source-linked event record to your HTTPS endpoint, signs the raw body, supplies a stable event ID, and retries transient failures without hiding terminal ones.
{
"id": "evt_…",
"type": "model_release",
"created_at": "2026-08-11T14:32:08Z",
"data": {
"provider": "openai",
"subject": { "type": "model", "key": "gpt-…" },
"title": "Model released",
"summary": "A source-linked change was confirmed.",
"evidence": "documented",
"confirmation": "confirmed",
"source_url": "https://…",
"source_published_at": "2026-08-11T14:30:00Z"
}
}Delivery contract
Signed, identifiable, and safe to replay
- Signing
- HMAC-SHA256
- Delivery
- at-least-once
- Timeout
- 10 seconds
- Pro destinations
- Up to 5
Verify the raw body before parsing JSON
Radar creates `Radar-Signature` from the Unix timestamp, a period, and the exact request body. The destination secret appears once when the webhook is created. Store it outside code and compare digests in constant time.
Radar-SignatureTimestamp and v1 HMAC digest
Radar-Event-IdStable event ID for deduplication
Idempotency-Keyradar-event-<event id>
import { createHmac, timingSafeEqual } from 'node:crypto'
const signature = request.headers.get('Radar-Signature')
const eventId = request.headers.get('Radar-Event-Id')
const [timestampPart, digestPart] = signature.split(',')
const timestamp = timestampPart.slice(2)
const received = digestPart.slice(3)
const expected = createHmac('sha256', process.env.RADAR_WEBHOOK_SECRET)
.update(`${timestamp}.${rawBody}`)
.digest('hex')
if (!timingSafeEqual(Buffer.from(received), Buffer.from(expected))) {
throw new Error('Invalid Radar signature')
}
// Deduplicate successful processing by eventId.Transient failures retry with bounded backoff
The first retry waits 30 seconds. Backoff doubles to a one-hour ceiling and stops after 8 attempts. A `429` response can supply `Retry-After`, also capped at one hour.
Permanent failures pause the destination
HTTP 400, 401, 403, 404, 405, 410, 422 responses are terminal. Radar records the failure and pauses the destination instead of hammering an endpoint that rejected the request. A successful destination test activates it again.
Receiver checklist
- 01Read and retain the exact raw body.
- 02Verify the HMAC before parsing or acting.
- 03Deduplicate successful work by Radar-Event-Id.
- 04Return a 2xx response inside ten seconds.
Destination URLs fail closed
Customer webhooks must use HTTPS. Embedded credentials, localhost, private-network targets, and redirects are rejected. Radar stores the destination and signing secret encrypted, then deletes both when the destination is removed.