Create a webinar
Creates a webinar owned by the API key's account, on the licence you name. Needs the webinars:write scope.
A scheduled webinar (the default) is published straight away: its page (pageUrl) goes live and, with access: registration, registration opens. Create it as a draft to keep it private.
Send an Idempotency-Key so a retry after a timeout can't create it twice.
apiKeyAuthorizationBearer <vk_live_<public id>_<secret>>An API key from the Vidyst studio (Developer → API keys), sent as Authorization: Bearer vk_live_….
Idempotency-Key?stringMakes the request safe to retry: a retry with the same key and body within 24 hours returns the first response instead of creating a second webinar. See Idempotency.
^[A-Za-z0-9_-]{8,128}$application/json- body
A new webinar. It's owned by the account the API key belongs to.
title*stringThe webinar's title (1–200 characters).
1 <= length <= 200licenceKey*stringThe key of the licence the webinar runs on, VDL-XXXXX-XXXXX-XXXXX-XXXXX: copy it from the Vidyst studio under Licences. Case and dashes don't matter. You must hold the licence (or own it while nobody else holds it), and it must be active.
length <= 40status?stringscheduled publishes it: its page goes live and registration opens (needs scheduledAt). draft keeps it private until you schedule it in the studio.
"scheduled""draft""scheduled"scheduledAt?stringWhen the (first) session starts: ISO 8601 with a UTC offset (Z or +05:30). Required unless status is draft.
^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$date-timetimezone?stringThe IANA time zone the webinar is shown in and its series repeats by (a weekly session stays at the same local time across daylight-saving changes).
length <= 64"UTC"durationMinutes?integerHow long each session is planned to last, in minutes (1–1440).
1 <= value <= 144060description?stringPlain text shown on the public page (up to 5,000 characters).
length <= 5000access?stringopen: anyone with the link can join. registration: people register first (with questions, if any).
"open""open""registration"registrationLimit?integerThe most registrations it takes (1–100,000). Leave it out for no limit beyond the licence's.
1 <= value <= 100000passcode?stringA passcode attendees must enter to join (4–64 characters). Never returned: the webinar shows passcodeProtected.
4 <= length <= 64reminders?array<>The emails registrants get: confirmation on registering, the timed ones before each session, replay after. Leave it out and none are sent.
items <= 8repeat?stringMakes it a series: daily, weekly or monthly from scheduledAt, or custom on the weekdays in repeatDays.
"none""none""daily""weekly""monthly""custom"repeatCount?integerHow many sessions a series has (2–52; 2 when left out). Ignored when repeat is none.
2 <= value <= 52repeatDays?array<>The weekdays of a custom series, 0 = Sunday to 6 = Saturday. Required for custom, and only custom takes them.
items <= 7agenda?array<>Up to 30 agenda lines for the public page.
items <= 30faqs?array<>Up to 20 questions and answers for the public page.
items <= 20questions?array<>Up to 20 questions on the registration form (used when access is registration).
items <= 20The webinar was created. With an Idempotency-Key seen before (same body), the webinar first created.
application/json- response
A webinar.
id*stringThe webinar's id.
^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$uuidtitle*stringIts title.
description*|Its plain-text description, or null.
status*stringdraft (private), scheduled (published, not live), live (a session is on) or ended (no sessions left).
"draft""scheduled""live""ended"access*stringopen or registration.
"open""registration"licenceKey*|The key of the licence it runs on.
scheduledAt*|When the first session starts (UTC), or null for a draft without a date.
timezone*stringThe IANA time zone it's shown in.
durationMinutes*integerPlanned length of each session, in minutes.
-9007199254740991 <= value <= 9007199254740991repeat*stringHow the series repeats (none for a single session).
"none""daily""weekly""monthly""custom"repeatCount*integerHow many sessions it has (1 for a single session).
-9007199254740991 <= value <= 9007199254740991repeatDays*array<>The weekdays of a custom series (0 = Sunday); empty otherwise.
occurrences*array<>Every session, in order.
nextSessionAt*|The session on now or the next one (UTC); null when none is left.
sessionsLeft*integerSessions not over yet, the one on now included.
-9007199254740991 <= value <= 9007199254740991registrationLimit*|The most registrations it takes, or null for no limit of its own.
registrationCount*integerHow many people have registered.
-9007199254740991 <= value <= 9007199254740991passcodeProtected*booleanWhether attendees need a passcode to join.
reminders*array<>The emails registrants get.
agenda*array<>The agenda shown on its page.
faqs*array<>The questions and answers shown on its page.
questions*array<>The registration form's questions.
pageUrl*stringIts public page, where people register and join. Share this link.
uristartedAt*|When its current or last session went live (UTC), or null.
endedAt*|When it ended for good (UTC), or null.
createdAt*stringWhen it was created (UTC).
^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$date-timeupdatedAt*stringWhen it last changed (UTC).
^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$date-timecurl -X POST 'https://vapi.vidyst.com/public/v1/webinars' \ -H 'Authorization: Bearer vk_live_…' \ -H 'Content-Type: application/json' \ -d '{ "title": "Product launch: what'\''s new in Q4", "licenceKey": "VDL-M4A05-TKY9Q-0A5V6-WMR8H"}'{ "id": "01929c5e-8f3a-7b21-9d4e-5a6b7c8d9e0f", "title": "Product launch: what's new in Q4", "description": "A tour of everything we shipped this quarter, with live Q&A.", "status": "scheduled", "access": "registration", "licenceKey": "VDL-M4A05-TKY9Q-0A5V6-WMR8H", "scheduledAt": "2026-12-01T15:30:00.000Z", "timezone": "Asia/Kolkata", "durationMinutes": 45, "repeat": "weekly", "repeatCount": 6, "repeatDays": [], "occurrences": [ { "index": 0, "startsAt": "2026-12-01T15:30:00.000Z", "done": false } ], "nextSessionAt": "2026-12-01T15:30:00.000Z", "sessionsLeft": 6, "registrationLimit": 500, "registrationCount": 0, "passcodeProtected": true, "reminders": [ "confirmation", "day_before", "hour_before" ], "agenda": [ { "time": "10:00", "title": "Welcome and introductions" } ], "faqs": [ { "question": "Will there be a replay?", "answer": "Yes, registrants get the replay by email." } ], "questions": [ { "label": "What's your role?", "type": "multiple_choice", "required": true, "options": [ "Marketing", "Engineering", "Other" ] } ], "pageUrl": "https://vidyst.live/w/4fQ9zK2mXp", "startedAt": null, "endedAt": null, "createdAt": "2026-11-03T09:30:00.000Z", "updatedAt": "2026-11-03T09:30:00.000Z"}Verify an API key GET
Checks the API key in the `Authorization` header and returns the key's name, scopes, expiry and rate-limit status. Use it to test a new key, to see which permissions a key has, or as a cheap health check for your integration. It needs no scope, and counts against the key's rate limit like any other request. A key that isn't valid gets a `401` (missing, invalid, expired or revoked) or a `403` (valid, but API access isn't enabled for the account or the request comes from outside the key's IP allowlist). The `code` field says which.
Get a webinar GET
One webinar the API key's account owns. Needs the `webinars:read` scope. A webinar that doesn't exist, or that the account doesn't own (even one it helps run), is `404 not_found`.