Integration guide Guide
Use Video Intros with any CRM
If your system knows that a customer moment happened, it can trigger Video Intros.
Your CRM
- Appointment booked
- Deal changed
- Milestone reached
- Project started
- Customer closed
POST
/v1/touchpoint-eventsVideo Intros
A personalized Video Intro from the right person.
Six steps
- Detect the business eventA webhook from your CRM, a database trigger, a job that polls. Any of them works.
- Map it to a touchpointKeep a small table from your event to the organization’s touchpoint slug. How touchpoints work.
- Create a deterministic idempotency key
your_crm:appointment_123:new_appointment. Why. - POST the touchpoint eventPOST /v1/touchpoint-events
- Store the returned event idIt is how you ask what happened.
- Retry safely when appropriateOn a timeout,
429or5xx, with the same key.
curl -X POST https://api.videointros.com/v1/touchpoint-events \
-H "Authorization: Bearer $VIDEO_INTROS_API_KEY" \
-H "Idempotency-Key: your_crm:appointment_123:new_appointment" \
-H "Content-Type: application/json" \
-d '{
"touchpoint": "new_appointment",
"occurred_at": "2026-10-05T17:40:00Z",
"member": {
"external_id": "rep_456"
},
"recipient": {
"first_name": "Andrea",
"last_name": "Smith",
"phone": "+12405550100"
},
"reference": {
"source": "your_crm",
"type": "appointment",
"id": "appointment_123"
},
"context": {
"appointment": {
"starts_at": "2026-10-06T18:00:00Z",
"timezone": "America/New_York"
}
}
}'
const response = await fetch("https://api.videointros.com/v1/touchpoint-events", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VIDEO_INTROS_API_KEY}`,
"Idempotency-Key": "your_crm:appointment_123:new_appointment",
"Content-Type": "application/json",
},
body: JSON.stringify({
"touchpoint": "new_appointment",
"occurred_at": "2026-10-05T17:40:00Z",
"member": {
"external_id": "rep_456"
},
"recipient": {
"first_name": "Andrea",
"last_name": "Smith",
"phone": "+12405550100"
},
"reference": {
"source": "your_crm",
"type": "appointment",
"id": "appointment_123"
},
"context": {
"appointment": {
"starts_at": "2026-10-06T18:00:00Z",
"timezone": "America/New_York"
}
}
}),
});
const result = await response.json();
import os, requests
response = requests.post(
"https://api.videointros.com/v1/touchpoint-events",
headers={
"Authorization": f"Bearer {os.environ['VIDEO_INTROS_API_KEY']}",
"Idempotency-Key": "your_crm:appointment_123:new_appointment",
},
json={
"touchpoint": "new_appointment",
"occurred_at": "2026-10-05T17:40:00Z",
"member": {
"external_id": "rep_456",
},
"recipient": {
"first_name": "Andrea",
"last_name": "Smith",
"phone": "+12405550100",
},
"reference": {
"source": "your_crm",
"type": "appointment",
"id": "appointment_123",
},
"context": {
"appointment": {
"starts_at": "2026-10-06T18:00:00Z",
"timezone": "America/New_York",
},
},
},
)
result = response.json()
{
"id": "evt_8f3c2a71d04e",
"object": "touchpoint_event",
"status": "accepted",
"touchpoint": "new_appointment",
"environment": "test",
"created_at": "2026-10-05T17:40:01Z"
}
When your application decides the message
If there is no touchpoint for what you are doing, or your product writes its own script, create the Video Intro directly.
{
"member": {
"email": "[email protected]"
},
"recipient": {
"first_name": "Andrea",
"last_name": "Smith",
"phone": "+12405550100"
},
"reference": {
"source": "your_app",
"type": "order",
"id": "order_981"
},
"context": {
"title": "Your kitchen consultation",
"appointment": {
"starts_at": "2026-10-06T18:00:00Z",
"timezone": "America/New_York"
}
},
"instructions": {
"script": "Hi Andrea, I'm Anthony. I'll be the one coming out tomorrow at 2:00 PM. I wanted you to see a friendly face before I get there."
},
"delivery": {
"responsibility": "integration"
},
"metadata": {
"order_id": "order_981"
}
}