VIDRIPDevelopersGet an API key
Vidrip Communities

Leads API

Your website tells Vidrip who just signed up. Someone on your team records a short welcome video for that person from the Vidrip app, they get a branded email, and they can reply on the spot. This API is how the signups get in, and how you read back what happened to each one.

1Your sitePOSTs a lead the moment someone signs up
2Your teamgets a push, records a welcome video in the app
3The persongets the email, watches, replies on the page
4Youread the lead back: welcomed, opened, replied

Everything is JSON over HTTPS. Timestamps are ISO 8601 in UTC. Responses are UTF-8 with content-type: application/json.

Authentication

Every request carries a community API key. Keys start with vk_live_ and are created by a community owner or admin at vidrip.app/account → Communities → Website connection. A key belongs to exactly one community and can be revoked at any time.

Authorization: Bearer vk_live_…
# or
x-api-key: vk_live_…

Keep keys server-side. A key can create, read, update and delete that community's leads, so it should never ship in a browser bundle or a mobile app.

The lead object

What every read returns. A lead is one person who signed up on your site.

{
  "id": "8d2a4c9e-3f7b-4b1e-9c2d-1a2b3c4d5e6f",
  "kind": "signup",
  "name": "Ana Lima",
  "email": "[email protected]",
  "meta": { "plan": "pro", "source": "pricing-page" },
  "idempotency_key": "email:[email protected]",
  "status": "sent",
  "created_at": "2026-09-18T14:02:11.000Z",
  "welcomed_at": "2026-09-18T14:19:40.000Z",
  "welcome": {
    "url": "https://vidrip.app/o/Xk3pQ9vT2mLa",
    "opened_at": "2026-09-18T15:01:02.000Z",
    "replied_at": null
  }
}
FieldTypeNotes
iduuidalwaysStable id for the lead. Use it for reads, updates and deletes.
kindstringalwaysWhat happened on your side. Default "signup". Free text up to 40 characters, e.g. "trial", "waitlist".
namestring | nullalwaysThe person’s name if you sent one. First name is used in the welcome script.
emailstringalwaysLowercased. Where the welcome email goes.
metaobjectalwaysWhatever you sent. Shown to the team. "source" or "utm_source" also feeds the dashboard’s source breakdown.
idempotency_keystringalwaysYours, or "email:<lowercased email>" by default.
statusenumalwaysopen · claimed · sent · dismissed. See below.
created_attimestampalwaysWhen the lead was created.
welcomed_attimestamp | nullalwaysWhen the welcome video and email were sent.
welcomeobject | nullalwaysPresent once welcomed: the page the person received, when they first opened it, and when they first replied.

Status values

FieldTypeNotes
openstatusWaiting for someone on the team to pick it up.
claimedstatusA team member is recording the welcome right now (a 15-minute hold). Reads as open again if it lapses.
sentstatusThe welcome video and email went out. welcome.url is live.
dismissedstatusRetired from active views, by the team or by you. A lead that was already welcomed keeps welcomed_at and welcome. Final.

Create a lead

POST/events

Call this the moment someone signs up. It returns 202 Accepted immediately; the welcome happens later, when a team member records it.

FieldTypeNotes
emailstringrequiredA valid address. Lowercased on the way in.
namestringoptionalUp to 80 characters. Without it the team sees the email and the script opens with "Hey there".
kindstringoptionalDefault "signup".
idempotency_keystringoptionalUp to 200 characters. Default is the email, so the same person never queues twice. Send your own user id to allow a second welcome for a changed address.
metaobjectoptionalUp to 4,000 characters of JSON. Anything useful to the person welcoming them.
// 202
{
  "ok": true,
  "event_id": "8d2a4c9e-…",
  "status": "open",         // or "unsubscribed" (event_id null): accepted, nothing queued
  "duplicate": false,       // true when the idempotency key already existed — the existing lead is returned
  "pushed": 3,              // team members notified
  "lead": { …the lead object… }
}

Create many

POST/events/batch

Up to 100 leads in one call, for imports and backfills. Each item is validated and created exactly like a single create, with the same idempotency. The team gets one push for the whole batch; pass "notify": false for none.

{ "leads": [ { "email": "[email protected]", "name": "Ana Lima" }, { "email": "[email protected]" } ], "notify": true }

// 202
{ "ok": true, "created": 2, "duplicates": 0, "unsubscribed": 0, "failed": 0,
  "results": [ { "index": 0, "ok": true, "event_id": "…", "status": "open", "duplicate": false }, … ] }

ok is false when any item failed; the per-item results say which and why. Valid items are still created.

List leads

GET/events

Newest first, 50 per page by default. Use next from one page as before on the next.

FieldTypeNotes
statusenumoptionalall (default) · open · claimed · sent · dismissed
limitnumberoptional1 to 200. Default 50.
beforetimestampoptionalOnly leads created before this time. Pass the previous page’s next.
qstringoptionalCase-insensitive match on email or name.
GET /events?status=sent&limit=100

// 200
{ "leads": [ { …lead… }, … ], "next": "2026-09-12T09:31:00.000Z" }   // next is null on the last page

Get a lead

GET/events/:id
// 200
{ "lead": { …lead… } }

Poll this, or the list filtered by status=sent, to sync welcome status and replies back into your CRM. A lead from another community answers 404.

Update a lead

PATCH/events/:id

Fix a name, change the address before the welcome goes out, or attach more context. Only the fields you send change.

FieldTypeNotes
namestring | nulloptionalUp to 80 characters.
emailstringoptionalAllowed while the lead is open, claimed or dismissed. Once welcomed the email already went out, so this answers 409.
kindstringoptional
metaobjectoptionalReplaces meta entirely.
{ "name": "Ana L.", "meta": { "plan": "team" } }

// 200
{ "lead": { …lead… } }

Delete a lead

DELETE/events/:id

Removes the lead outright: a mistaken signup, a test, a request to be forgotten. Allowed for open, claimed and dismissed leads. Once welcomed, the video and the reply thread exist, so a welcomed lead answers 409 — dismiss it instead, which always succeeds.

// 200
{ "ok": true }

Dismiss a lead

POST/events/:id

Take a lead out of active views without deleting it. Works at any stage, including after the welcome: the record stays, marked dismissed, and the welcome video and reply thread are preserved. Use it to retire test leads and people who cancelled. Dismissing an already-dismissed lead returns 200 with the lead unchanged.

{ "action": "dismiss" }

// 200
{ "lead": { …lead, "status": "dismissed" } }

What happens next

  1. Every team member gets a push. The lead appears in their queue in the Vidrip app.
  2. One of them claims it and records a short welcome on camera, with a teleprompter built from your community's template and the person's first name.
  3. The person receives the branded welcome email from your community's address or from Vidrip. The lead's status becomes sent and welcome.url is live.
  4. They watch on the page and reply, in text or on video. The first reply sets welcome.replied_at and the team gets a push.
  5. If they sign up or log in on the page, they connect with your community, and your team can message them in the app from then on.

Limits and idempotency

  • Idempotent by email. The same idempotency key never creates a second lead in a community. A repeat returns the existing lead with duplicate: true and nobody is notified again. Retrying a failed request is always safe.
  • Unsubscribes are honoured for you. Every welcome email carries a one-click unsubscribe. A lead for an unsubscribed address is accepted and skipped with status: "unsubscribed".
  • 500 new leads per community per day. Above that the API answers 429. Ask us if you need more.
  • 100 leads per batch call. 200 per list page.

Errors

Errors are JSON with a single human-readable error field.

FieldTypeNotes
400statusValidation: a missing or invalid email, oversized meta, an unknown status filter.
401statusMissing, invalid or revoked API key.
403statusThe key belongs to another community, or the action is not allowed with a key.
404statusNo such lead in this community.
409statusConflict: changing the email of a welcomed lead, deleting a welcomed lead (dismiss instead), or an email another lead already has. Dismissal never returns 409.
429statusDaily limit reached.
{ "error": "a valid email is required" }

Examples

curl

curl -X POST https://vidrip.app/api/outreach/events \
  -H "Authorization: Bearer $VIDRIP_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Ana Lima", "email": "[email protected]", "meta": { "plan": "pro", "source": "pricing-page" } }'

Node

const res = await fetch('https://vidrip.app/api/outreach/events', {
  method: 'POST',
  headers: { authorization: `Bearer ${process.env.VIDRIP_KEY}`, 'content-type': 'application/json' },
  body: JSON.stringify({ name: user.name, email: user.email, idempotency_key: `user:${user.id}`, meta: { plan: user.plan } }),
});
const { event_id, duplicate } = await res.json();

Sync welcome status back (Node)

let before = null;
do {
  const url = new URL('https://vidrip.app/api/outreach/events'); url.searchParams.set('status', 'sent'); url.searchParams.set('limit', '200');
  if (before) url.searchParams.set('before', before);
  const { leads, next } = await (await fetch(url, { headers: { authorization: `Bearer ${process.env.VIDRIP_KEY}` } })).json();
  for (const lead of leads) crm.update(lead.email, { welcomedAt: lead.welcomed_at, repliedAt: lead.welcome?.replied_at ?? null });
  before = next;
} while (before);

Python

import os, requests
r = requests.post("https://vidrip.app/api/outreach/events",
    headers={"Authorization": f"Bearer {os.environ['VIDRIP_KEY']}"},
    json={"name": "Ana Lima", "email": "[email protected]", "meta": {"plan": "pro"}})
print(r.status_code, r.json())   # 202 {'ok': True, 'event_id': '…', 'status': 'open', ...}
Ready to connect your site?

Create a community, mint a key, send your first lead.