Event Payloads
Every webhook delivery uses the same envelope: event, event_id, timestamp, workspace_id, client_id and data.
event_idevent_id is a UUID generated once when the event is queued and is stable across all retry attempts — the stored payload is delivered as-is on every attempt. Use it as a deduplication key per webhook endpoint. When multiple webhooks in the same workspace match an event, they all receive the same event_id, so dedupe per endpoint, not globally.
client_id is null for workspace-wide (org-level) events without a client context, and contains the client workspace UUID for client-scoped events. Org-wide webhooks receive both; client-scoped webhooks only receive events for their own client_id.
- lead.created
- lead.replied
- lead.bounced
- lead.updated
- reply.sent
- corty.suggested
- reply.queued
- reply.approved
- report.generated
{
"event": "lead.created",
"event_id": "uuid",
"timestamp": "2026-03-21T10:00:00Z",
"workspace_id": "org-abc123",
"client_id": null,
"data": {
"from_email": "john@acme.com",
"from_name": "John Doe",
"campaign_id": "uuid",
"campaign_name": "Q1 SaaS Outreach",
"first_seen_at": "2026-03-21T10:00:00Z"
}
}
{
"event": "lead.replied",
"event_id": "uuid",
"timestamp": "2026-03-20T14:30:00Z",
"workspace_id": "org-abc123",
"client_id": null,
"data": {
"email": "john@acme.com",
"first_name": "John Doe",
"campaign_id": "uuid",
"reply_id": "uuid",
"reply_text": "Sounds interesting, can we schedule a call?",
"classification": null
}
}
reply_text is truncated to 500 characters. Use GET /v1/replies/:id (with the included reply_id) for the full body and thread. classification is null at the time of this event — classification happens asynchronously afterward.
{
"event": "lead.bounced",
"event_id": "uuid",
"timestamp": "2026-03-20T14:30:00Z",
"workspace_id": "org-abc123",
"client_id": null,
"data": {
"reply_id": "uuid",
"from_email": "john@acme.com",
"campaign_id": "uuid",
"campaign_name": "Q1 SaaS Outreach",
"bounce_type": "hard"
}
}
{
"event": "lead.updated",
"event_id": "uuid",
"timestamp": "2026-03-21T10:00:00Z",
"workspace_id": "org-abc123",
"client_id": null,
"data": {
"lead_id": "uuid",
"email": "john@acme.com",
"campaign_id": "uuid",
"classification": "hot",
"notes": "Spoke on phone, very interested"
}
}
{
"event": "reply.sent",
"event_id": "uuid",
"timestamp": "2026-03-20T14:30:00Z",
"workspace_id": "org-abc123",
"client_id": null,
"data": {
"reply_id": "uuid",
"to_email": "john@acme.com",
"to_name": "John Doe",
"campaign_id": "uuid",
"body": "Hey John, great to hear you're interested...",
"similarity_score": 0.92
}
}
{
"event": "corty.suggested",
"event_id": "uuid",
"timestamp": "2026-03-20T14:30:00Z",
"workspace_id": "org-abc123",
"client_id": null,
"data": {
"lead_email": "john@acme.com",
"campaign_id": "uuid",
"reply_id": "uuid",
"suggestion": "Hey John, thanks for your interest...",
"confidence": 0.87,
"tone": "hot"
}
}
suggestion is truncated to 500 characters. Use GET /v1/replies/:id for the full context.
{
"event": "reply.queued",
"event_id": "uuid",
"timestamp": "2026-03-21T10:00:00Z",
"workspace_id": "org-abc123",
"client_id": "client-456",
"data": {
"reply_id": "uuid",
"to_email": "john@acme.com",
"draft_body": "Hey John, great question — here is how that works...",
"api_key_name": "FutureMarketingAI",
"reason": "no_active_autonomy_grant"
}
}
Fired when an external agent submits a draft via POST /v1/replies/:id/send at autonomy level 0. The draft is in the review queue awaiting human approval.
{
"event": "reply.approved",
"event_id": "uuid",
"timestamp": "2026-03-21T10:05:00Z",
"workspace_id": "org-abc123",
"client_id": "client-456",
"data": {
"reply_id": "uuid",
"to_email": "john@acme.com",
"approver": "Daley van Nooij",
"api_key_name": "FutureMarketingAI",
"sent_at": "2026-03-21T10:05:00Z"
}
}
Fired when a queued draft is approved via POST /v1/replies/:id/approve. The reply has been sent.
{
"event": "report.generated",
"event_id": "uuid",
"timestamp": "2026-03-21T17:00:00Z",
"workspace_id": "org-abc123",
"client_id": null,
"data": {
"report_id": "uuid",
"report_type": "friday",
"title": "Friday Intelligence Brief — 21 mrt 2026",
"executive_summary": "Corty improved 3 campaigns, caught 2 issues.",
"period_start": "2026-03-17",
"period_end": "2026-03-21"
}
}