lead.createdNew lead from any source.{
"id": "evt_01HXYZ...",
"type": "lead.created",
"createdAt": "2026-05-05T13:32:00Z",
"data": {
"id": "lead-1",
"name": "Olivia Carter",
"source": "website",
"score": 78
}
}13 event types. HMAC-SHA256 signed. Exponential-backoff retries up to 24 hours. Inspect, replay, and dead-letter from the dashboard.
The event catalog, payload shapes, and signature scheme on this page are final — build your handler against them today and it works unchanged on day one. Delivery, subscriptions, and the replay UI go live in Q3 2026.
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifyAdpWebhook(
rawBody: string,
signature: string,
timestamp: string,
secret: string,
): boolean {
// Reject stale events (clock-drift safe)
const ts = parseInt(timestamp, 10);
if (!ts || Math.abs(Date.now() / 1000 - ts) > 300) return false;
// Recompute the signature
const expected = createHmac('sha256', secret)
.update(`${timestamp}.${rawBody}`)
.digest('hex');
// Constant-time compare
const a = Buffer.from(expected);
const b = Buffer.from(signature);
if (a.length !== b.length) return false;
return timingSafeEqual(a, b);
}
// Usage in your handler:
//
// const sig = req.headers.get('x-adp-signature') ?? '';
// const ts = req.headers.get('x-adp-timestamp') ?? '';
// if (!verifyAdpWebhook(rawBody, sig, ts, process.env.ADP_WEBHOOK_SECRET!)) {
// return new Response('invalid', { status: 401 });
// }lead.createdNew lead from any source.{
"id": "evt_01HXYZ...",
"type": "lead.created",
"createdAt": "2026-05-05T13:32:00Z",
"data": {
"id": "lead-1",
"name": "Olivia Carter",
"source": "website",
"score": 78
}
}lead.qualifiedLead score crossed your threshold.{
"id": "evt_01HXYZ...",
"type": "lead.qualified",
"createdAt": "2026-05-05T13:32:00Z",
"data": {
"id": "lead-2",
"score": 92,
"threshold": 85
}
}lead.convertedLead became a deal.{
"id": "evt_01HXYZ...",
"type": "lead.converted",
"createdAt": "2026-05-05T13:32:00Z",
"data": {
"id": "lead-1",
"dealId": "d-1"
}
}deal.createdPencil opened on a unit.{
"id": "evt_01HXYZ...",
"type": "deal.created",
"createdAt": "2026-05-05T13:32:00Z",
"data": {
"id": "d-1",
"vehicleId": "a4830",
"stage": "pencil"
}
}deal.signedCustomer signed paperwork.{
"id": "evt_01HXYZ...",
"type": "deal.signed",
"createdAt": "2026-05-05T13:32:00Z",
"data": {
"id": "d-1",
"signedAt": "2026-05-05T16:14:00Z"
}
}deal.fundedLender released funds.{
"id": "evt_01HXYZ...",
"type": "deal.funded",
"createdAt": "2026-05-05T13:32:00Z",
"data": {
"id": "d-1",
"fundedAt": "2026-05-06T10:32:00Z",
"totalCents": 412000
}
}unit.createdVehicle hit the lot.{
"id": "evt_01HXYZ...",
"type": "unit.created",
"createdAt": "2026-05-05T13:32:00Z",
"data": {
"id": "a4830",
"vin": "JTM...",
"stockNumber": "A4830"
}
}unit.soldVehicle marked sold.{
"id": "evt_01HXYZ...",
"type": "unit.sold",
"createdAt": "2026-05-05T13:32:00Z",
"data": {
"id": "a4830",
"dealId": "d-1"
}
}unit.agedVehicle past your aging threshold.{
"id": "evt_01HXYZ...",
"type": "unit.aged",
"createdAt": "2026-05-05T13:32:00Z",
"data": {
"id": "b2099",
"daysOnLot": 64,
"threshold": 60
}
}call.completedHerald call ended (transcript ready).{
"id": "evt_01HXYZ...",
"type": "call.completed",
"createdAt": "2026-05-05T13:32:00Z",
"data": {
"id": "call-1",
"durationSec": 222,
"outcome": "appointment_set"
}
}call.escalatedHerald handed off to human.{
"id": "evt_01HXYZ...",
"type": "call.escalated",
"createdAt": "2026-05-05T13:32:00Z",
"data": {
"id": "call-2",
"reason": "service_question",
"transferredTo": "sofia-park"
}
}service.openedNew repair order.{
"id": "evt_01HXYZ...",
"type": "service.opened",
"createdAt": "2026-05-05T13:32:00Z",
"data": {
"id": "ro-1",
"vin": "4S4...",
"estimatedTotalCents": 18750
}
}service.completedRO closed, customer notified.{
"id": "evt_01HXYZ...",
"type": "service.completed",
"createdAt": "2026-05-05T13:32:00Z",
"data": {
"id": "ro-1",
"completedAt": "2026-05-05T15:30:00Z"
}
}The verify.ts snippet above works unchanged when delivery goes live in Q3 2026. Meanwhile the read API is open right now — try it in the sandbox, no signup.