Send VideoAsk Responses to Klaviyo
Time: ~15 minutes | Difficulty: Beginner | Prerequisites: A VideoAsk form you can edit, a Klaviyo private API key, Slashbin account
TL;DR: Two facts about this pipeline are not true of any other one documented here. VideoAsk does not sign its webhooks — it sends a shared token in a header you name yourself, and Slashbin compares it directly. And a Klaviyo destination receives your transformed payload verbatim — no slashbin_job_id wrapper, no metadata, no nesting. Your Golden Model's output is the body Klaviyo receives. Get either wrong and the integration fails in a way that looks like something else.
The Problem
You want a video response — a lead who recorded an answer on your VideoAsk form — to land in Klaviyo as an event, so a flow can pick it up. Both ends of that pipeline break a rule the rest of our recipes taught you.
- You went looking for VideoAsk's signing algorithm. There isn't one. Every other source documented here — Stripe, Square, GitHub, Typeform, QuickBooks — computes an HMAC digest over the request body. VideoAsk sends a static shared token in a header. There is no digest, no encoding, and no signing payload to get wrong.
- You assumed the header name was VideoAsk's to choose. It is yours. You define both the header name and its value when you configure the webhook, which means the name has to match on both sides or nothing verifies.
- Your transform produced a body Klaviyo rejects. Every other destination type receives a Slashbin envelope with your payload nested inside it. Klaviyo does not. A model written against the wrapped shape sends Klaviyo an object it has no schema for, and the 400 that comes back looks like a mapping bug rather than a shape mismatch.
- Your routing rules stopped matching after someone edited the form. VideoAsk sends no event-type field. The topic is the form's title — a human-editable label — so a rename in the VideoAsk editor changes the value your rules match on.
None of these are Klaviyo bugs or VideoAsk bugs. They are properties of how the two ends are configured, and each one is invisible until it costs you an afternoon.
The Solution
Route VideoAsk through a Slashbin project with a Klaviyo destination. The token comparison, the topic path, and the Klaviyo request contract all become stored configuration:
- The raw payload exactly as VideoAsk sent it — bytes and headers.
- Header-token verification at the gateway, in constant time, before your Golden Model or Klaviyo sees anything.
- The resolved topic — what Slashbin read out of
$.form.titlefor that specific response. - The transform result — the Klaviyo Events object your model produced, or the error it threw.
- Every delivery attempt to Klaviyo — response code, response body, and timing — plus replay from Slashbin's own storage.
Outcome: VideoAsk only has to reach Slashbin once. Klaviyo's 400s become readable response bodies in a delivery log instead of a silence you have to reproduce.
Step 1: Create a VideoAsk Project in Slashbin
- Click Create New Project and select VideoAsk.
- Type: Choose Transactional — a form response is a discrete business event, not a metric.
Selecting VideoAsk loads its verification contract into the project — and it is a different shape from every other one in these recipes:
| Field | VideoAsk's value |
|---|---|
| Auth type | Header value — not HMAC |
| Secret field | Secret Value on screen — VideoAsk's Header Token |
| Header name | (empty and required — you type it. x-videoask-signature is the conventional choice) |
| Signature encoding | (not used — nothing is encoded) |
| Signed payload | (not used — nothing is signed) |
| Event topic | $.form.title, read from the body |
VideoAsk is not HMAC. Do not reuse the check you wrote for another source. On the header-value path Slashbin does exactly one thing: a constant-time comparison of the header's value against the stored Header Token. There is no digest computed, no raw body captured for signing, and no sha256= prefix to strip. If you arrived here from the Stripe, Square, GitHub, Typeform or QuickBooks recipes and went hunting for VideoAsk's signing algorithm and encoding, stop — the fields are greyed out because they do not apply, not because they are optional.
Slashbin's gateway has no VideoAsk-specific code path. VideoAsk works because that contract is stored and applied on every request — the same mechanism that verifies the HMAC sources, taking a different branch.
Step 2: Set the Header Name and Secret
The header name is yours to choose — VideoAsk does not fix one and Slashbin does not prefill one. Set both values in Slashbin first, then copy them outward into VideoAsk.
- In Slashbin, type a Header Name. The field is empty and required — the wizard will not advance without it.
x-videoask-signatureis a fine choice if you have no preference; any name works as long as VideoAsk sends the same one. - Selecting VideoAsk already generated a secret and put it in the Secret Value field — VideoAsk's Header Token. Copy it now: it is shown once, and you will not be able to view it again. Click Generate New for a different one, or paste your own strong random string over it.
- In VideoAsk, open the form's webhook settings and add the Slashbin Ingestion URL as the endpoint.
- In VideoAsk, add a custom header using the same name you typed in Slashbin, and paste the copied secret as its value.
- Submit a test response, then open the Slashbin Delivery Log. A verified delivery is proof that the name and the value match on both sides.
The header name must match, and a mismatched name fails exactly like a wrong token. Slashbin looks for one specific header. If VideoAsk is sending x-videoask-secret and Slashbin is looking at x-videoask-signature, the header Slashbin reads is absent, the comparison fails, and the rejection is indistinguishable from a bad secret. Check the name before you regenerate the value.
Rotating the token later means updating it in both places. Until both sides match, verification fails closed, and every rejection is visible in the Delivery Log rather than lost.
Step 3: Transform the Response Into a Klaviyo Event
Read this before you write the model: a Klaviyo destination receives your transformed payload verbatim. For every other destination type, Slashbin wraps your payload in an envelope — slashbin_job_id, project_id, topic, transformed_at, metadata, and your payload nested under payload. For Klaviyo, that wrapper is absent. The bytes your Golden Model produces are the bytes Klaviyo's Events API receives. So your model's output has to be a valid Klaviyo Events object at the top level — not a record you expect something downstream to unwrap.
What VideoAsk sends
A VideoAsk form response arrives shaped roughly like this:
{
"event_type": "form_response",
"event_id": "01J6WQ4C7K2M9N3P5R7T9V1X3Z",
"interaction_id": "a8f21c04-6b3e-4f1d-9c72-0d5e6a1b8c34",
"form": {
"form_id": "f0f4a7c2",
"title": "Demo Request"
},
"contact": {
"contact_id": "c7d1e9b3",
"name": "Lauren Ramirez",
"email": "[email protected]",
"phone_number": "+15125550123",
"answers": [
{
"question_id": "q1",
"question_label": "What are you trying to solve?",
"type": "video",
"media_url": "https://media.videoask.com/...",
"transcript": "We are drowning in webhook plumbing."
}
]
}
}Field names vary with how the form is built, so read the stored raw body of your first real delivery rather than mapping against this example. That is what the raw payload is stored for.
The topic is the form's title
VideoAsk does not send an event-type field you can route on the way Stripe or Typeform do. Slashbin reads the topic from $.form.title — the form's own name — because that is the field that identifies which form a response came from. It is an identifier of convenience, not a contract, and one consequence follows directly:
Renaming a form in VideoAsk changes the topic your rules match on. "Demo Request" becomes "Demo Request 2026" in the editor and every routing rule written against the old title stops matching — silently, because an unmatched event is not an error. If you rename forms, update the rules in the same sitting, and check the resolved topic on a recent delivery to confirm what the rules are actually seeing.
If one project takes responses from several forms, that is exactly what the topic is for: one rule per form title, each pointing at the destination that should own it.
Map it into a Klaviyo Events object
Define the mapping once in the Transformation IDE. The target shape is Klaviyo's Events API request body, and — per the callout above — it is the whole output, top level:
{
"data": {
"type": "event",
"attributes": {
"properties": {
"form_title": "Demo Request",
"interaction_id": "a8f21c04-6b3e-4f1d-9c72-0d5e6a1b8c34",
"transcript": "We are drowning in webhook plumbing."
},
"metric": {
"data": {
"type": "metric",
"attributes": { "name": "VideoAsk Response" }
}
},
"profile": {
"data": {
"type": "profile",
"attributes": { "email": "[email protected]" }
}
}
}
}
}The fields that carry the VideoAsk response into it:
| Target path | Source JSONPath | Notes |
|---|---|---|
data.attributes.profile.data.attributes.email | $.contact.email | Required — Klaviyo needs an identifier to attach the event to a profile |
data.attributes.metric.data.attributes.name | (constant) | The metric name your Klaviyo flow triggers on |
data.attributes.properties.form_title | $.form.title | Required — the same value the topic resolves to |
data.attributes.properties.interaction_id | $.interaction_id | Good idempotency key for the response |
data.attributes.properties.transcript | $.contact.answers[0].transcript | Optional — one answer's transcript, if your form captures video |
Toggle Required ON for the profile identifier and the form title. An event Klaviyo cannot attach to a profile is one it will reject, and better that it is held as invalid than sent to be refused.
Click Publish to activate the model. Unpublished models don't drop events: incoming responses are captured in the Dead Letter Queue until a matching model is live, so nothing is lost while you iterate.
Step 4: Add Klaviyo as the Destination
On the Outbound tab, click + Add Destination and choose Klaviyo. The request contract is fixed by the destination type:
| Field | Value |
|---|---|
| Method and URL | POST https://a.klaviyo.com/api/events/ |
Authorization | Klaviyo-API-Key pk_... |
revision | 2024-10-15 |
Content-Type | application/json |
| Body | your transformed payload, verbatim |
Two conveniences worth knowing:
- The bare key is fine. Paste
pk_...on its own and Slashbin adds theKlaviyo-API-Keyprefix for you. Pasting the fullKlaviyo-API-Key pk_...string works too — it is not double-prefixed. revisiondefaults to2024-10-15. Leave it unset and Slashbin sends that value. Set it explicitly if you are pinning to a different Klaviyo API revision.
From there the guarantees are Slashbin's:
- Transient failure → retry with backoff. Klaviyo returning 429 or 502 for ninety seconds costs you nothing.
- Exhausted attempts → the Dead Letter Queue, holding the original raw VideoAsk payload, not a summary of it.
- Fixed the model → Replay. Slashbin re-delivers from its own storage, through the current model. Correct the profile mapping on Thursday and re-run Monday's responses through it — VideoAsk is not involved and does not need to be.
- Klaviyo rejected it? Read why. The attempt record carries Klaviyo's exact response body, which is where a shape error in your Events object shows up as a sentence rather than a status code.
Why Slashbin vs a Raw Handler
- The "where's the HMAC" question never comes up. Header name, token, constant-time comparison — stored as configuration and applied at the gateway. You do not write a second, different verification path just because this one source is not signed.
- The Klaviyo client you didn't write. URL, authorization scheme, and revision header come with the destination type. Your work is the payload shape, not the transport.
- Body-based routing without body-parsing code.
$.form.titleis a stored topic path, so telling three forms apart is three rules rather than an if-else chain overbody.form. - A rename is visible instead of silent. The resolved topic is recorded per delivery, so "why did this form stop routing" is one look at the Delivery Log.
- Delivery is retried and replayable. A video response is a person who recorded an answer and moved on. VideoAsk will not re-send it for you; Slashbin will.
Next Steps
- See the HMAC contract this source doesn't use — Send Typeform Submissions Anywhere covers the closest equivalent for form submissions.
- Compare another body-topic source with a nested path — Route LinkedIn Organization Webhooks.
- Go deeper on mapping and validation — read Golden Model.
- Send one response to more than one system — see Fan-Out Routing.
- Browse every supported source and destination on Integrations.