Skip to main content

Webhooks

Showdini can POST to an endpoint you control when something happens on a demo. Configure webhooks per demo show in the Showdini app.

Events

EventFires when
lead.report_generatedA visitor finished a demo and their lead report has been generated.

You can also send a test event from the app to check your endpoint before going live.

Request

Showdini sends a POST with a JSON body.

HeaderValue
Content-Typeapplication/json
X-Webhook-EventThe event name, e.g. lead.report_generated
AuthorizationBearer <your secret> — only if you configured a secret

Your endpoint must be a public http or https URL. Private, loopback, and link-local addresses are rejected, and redirects are not followed.

Delivery

  • Timeout: 10 seconds per attempt.
  • Retries: up to 2 attempts total, 5 seconds apart.
  • Success: any 2xx response. Anything else counts as a failure and is retried.

Respond 200 as soon as you have accepted the payload and do the real work asynchronously — slow endpoints get retried and then given up on.

Every delivery, successful or not, is recorded in the delivery log in the app so you can see the status code and response body we received.

Payload

Every event uses the same envelope:

{
"event": "lead.report_generated",
"demoShowId": "6712f0a1b2c3d4e5f6a7b8c9",
"timestamp": "2026-08-31T10:04:12.512Z",
"data": { }
}

lead.report_generated

data contains the lead and the session it came from:

FieldTypeDescription
sessionIdstringThe demo session.
reportIdstringThe generated report.
demoShowIdstringThe demo show the session belongs to.
demoShowNamestringHuman-readable demo name.
emailstring | nullLead email, if the visitor gave one.
customFieldsobjectValues collected by your demo's form fields.
metadataobjectYour own key/value data. See Metadata.
leadScorenumberLead score for the session.
insightsstring | nullAI-generated summary of the conversation.
timelinearrayOrdered events that happened during the session.
interactedCtabooleanWhether the visitor interacted with the CTA.
interactedCtaAtstring | nullISO timestamp of that interaction.
startedAt / endedAtstringISO timestamps bounding the session.
playedClipsarrayWhich demo clips were played.
languagestring | nullLanguage the demo ran in.
detectedLanguagesstring[]Languages detected during the conversation.
country / city / timezonestring | nullApproximate visitor location.
userAgentstring | nullVisitor's browser user agent.
embeddedbooleanWhether the demo ran embedded in another site.
leadUrlstringDeep link to the lead in the Showdini app.
transcriptarrayFull conversation transcript.

Verifying a request

If you set a secret on the webhook, Showdini sends it as a bearer token. Compare it against your stored value before trusting the payload:

app.post("/showdini-webhook", express.json(), (req, res) => {
const token = req.get("authorization")?.replace("Bearer ", "");

if (token !== process.env.SHOWDINI_WEBHOOK_SECRET) {
return res.sendStatus(401);
}

res.sendStatus(200); // acknowledge first
handleLead(req.body).catch(console.error); // then do the work
});
note

The secret is a shared bearer token, not an HMAC signature of the body. Always serve your webhook endpoint over HTTPS so the token is not sent in the clear.