Webhook receipt is not CRM proof
Returning 200 confirms receipt by the handler, not that the downstream sales system accepted the qualified lead.
ElevenLabs post-call CRM delivery
Verify signed ElevenLabs post-call events, queue only approved data collection results, and turn each qualified conversation into a duplicate-safe CRM delivery receipt.
Paid plan uses secure Stripe checkout · plan assigned after verified payment · activate with the checkout emailElevenLabs sends post_call_transcription only after the call and analysis are complete, but a successful webhook receipt still does not prove the CRM stored the qualified lead. The handler must verify the ElevenLabs-Signature against the untouched body, select only authorized data_collection_results, acknowledge promptly, and preserve conversation_id across retries.
ElevenLabs post_call_transcription -> signed mapping handler -> durable queue -> LeadProof -> CRMReturning 200 confirms receipt by the handler, not that the downstream sales system accepted the qualified lead.
ElevenLabs documents identical retry payloads, so conversation_id must remain the stable identity through every delivery attempt.
The post-call event can include extensive call artifacts; the CRM handoff should select only approved data collection results.
Implementation
Keep the tools that create and process the lead. Standardize only the fragile handoff between them.
Platform reference: ElevenLabs post-call webhook documentation ↗Open sandbox instructions →https://leadproof.jessesay.chatgpt.site/api/v1/leadsimport { ElevenLabsClient } from "elevenlabs";
const elevenlabs = new ElevenLabsClient();
export async function POST(request: Request) {
const rawBody = await request.text();
const signature = request.headers.get("ElevenLabs-Signature");
let event;
try {
event = await elevenlabs.webhooks.constructEvent(
rawBody,
signature,
process.env.ELEVENLABS_WEBHOOK_SECRET
);
} catch {
return Response.json({ error: "Invalid signature" }, { status: 401 });
}
if (event.type !== "post_call_transcription") {
return Response.json({ received: true }, { status: 200 });
}
const conversationId = event.data?.conversation_id;
const fields = event.data?.analysis?.data_collection_results;
const lead = {
name: fields?.name?.value,
email: fields?.email?.value,
phone: fields?.phone?.value
};
if (conversationId && lead.name && lead.email) {
await deliveryQueue.send({ conversationId, lead });
}
return Response.json({ received: true }, { status: 200 });
}
export async function deliverElevenLabsLead({ conversationId, lead }) {
const response = await fetch(
"https://leadproof.jessesay.chatgpt.site/api/v1/leads",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.LEADPROOF_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": conversationId
},
body: JSON.stringify({
destination: process.env.CRM_WEBHOOK_URL,
...lead,
source: "elevenlabs_post_call"
})
}
);
if (!response.ok) throw new Error("Lead delivery failed");
const delivery = await response.json();
await persistReceipt(conversationId, delivery.receipt?.id);
}Questions
ElevenLabs documents this event as occurring after a call finishes and analysis is complete, which is when data collection results are available.
The retry payload is identical, but the same conversation_id becomes the LeadProof Idempotency-Key so the CRM write remains duplicate-safe.
No. It reads only named values from data_collection_results and places those approved fields in the delivery job.
Get an explainable risk score, prioritized fixes, and the right LeadProof plan.