What these events do
Your service translates support-platform events into Voiceflow’s handoff events. Send them to the runtime’s POST /handoff/webhook/custom route. Use the runtime base URL for your deployment; for the hosted runtime this is https://general-runtime.voiceflow.com/handoff/webhook/custom.
Event envelope and payload
Every request contains projectId and events. Send one event per request. The parser accepts 1–50 events; single-event delivery makes retries and failures easier to isolate.
Every event requires a stable id, conversationId, timestamp string, and type. Use the conversation ID returned by your connection service.
Internal notes and echoed customer messages must not become message.received. Files must be retrievable without a vendor credential. The current custom event vocabulary does not include typing or queue-position events.
Example human reply
Replace IDs and timestamp with values from the active conversation. Do not send this historical timestamp as a live signature timestamp.
Sign, deliver and retry
Set X-Signature-Timestamp to the current Unix timestamp in seconds. Compute HMAC-SHA256 over the timestamp string concatenated directly with JSON.stringify(body), encode the digest as base64, and set X-Signature: primary=DIGEST. Use the same Webhook secret configured in Voiceflow; it must be at least 32 characters.
The runtime validates within a five-minute clock window. It verifies serialized parsed JSON, not the raw request bytes: build and send one JSON object consistently. Rotation can include a secondary=DIGEST signature.
The starter signing helper implements this format. Retain the event ID across retries, refresh the signature timestamp, and deliver from a durable outbox. A 401 requires fixing signing; a 404 can mean the conversation is not active or creation has not completed. Retry an early callback only while creation is known to be pending; stop replaying events for closed sessions. A 2xx response acknowledges processing, not proof the customer has read the message.