Overview
Everything your organization has on the dashboard — its webinars, their sessions, registrations and ratings, its VSLs, the sales counted to them, its surveys and their responses, its pages, its webhooks — is read and, where it makes sense, written through the public API, so your own systems and the tools you wire together can work with it.
https://api.sparkwebinar.io/public/v1Authentication
Section titled “Authentication”Every request carries your organization’s API token as a bearer:
Authorization: Bearer <token>The token is on the dashboard, under Settings, for owners and managers, and can be generated anew there — the old one stops working at once. The token names the organization, so no route does: everything you read and write is your organization’s, and anything else is answered as not found.
| Status | infoCode |
Why |
|---|---|---|
| 401 | UNAUTHENTICATED |
No bearer in the request, or a header not of that form. |
| 401 | API_TOKEN_INVALID |
A token that names no organization — generated anew since, or never ours. |
| 403 | ORGANIZATION_UNAVAILABLE |
The organization is not served — suspended, locked, or with no plan. |
Call it from a server. There is no CORS on the public API: a page in a browser cannot call it, and should not — the token would be in the page.
Answers
Section titled “Answers”Every answer is JSON in the same envelope. The status is on the wire;
the body is data, and metadata where there is more to say.
{ "data": { "id": 12, "name": "Launch webinar", "..." : "..." } }A list answers a page of items, and in metadata.list the page it is
and how many there are in all:
{ "data": [ { "id": 41, "...": "..." }, { "id": 40, "...": "..." } ], "metadata": { "list": { "pagination": { "page": 1, "size": 20 }, "total": 57 } }}A failure is data: null, and an infoCode where there is one to give:
{ "data": null, "metadata": { "infoCode": "WEBINAR_NOT_FOUND" } }| Status | infoCode |
Why |
|---|---|---|
| 400 | VALIDATION_FAILED |
A body, a query string or an id that does not fit the route. |
| 404 | <RESOURCE>_NOT_FOUND |
Nothing of your organization’s by that id — WEBINAR_NOT_FOUND, WEBINAR_REGISTRATION_NOT_FOUND, SURVEY_NOT_FOUND, SURVEY_RESPONSE_NOT_FOUND, CUSTOM_PAGE_NOT_FOUND, ORGANIZATION_WEBHOOK_NOT_FOUND, WEBINAR_TICKET_ORDER_NOT_FOUND, AB_TEST_NOT_FOUND, VSL_NOT_FOUND. |
| 409 | … |
The request is well-formed and cannot be done as things are; each route says its codes. |
| 429 | TOO_MANY_REQUESTS |
Over the limit below. |
A route that deletes answers 200 with data: null.
A list takes its page in the query string: page, from 1, and size, up
to 100 — twenty by default. Its filters go beside them, each a query
parameter named after the field it narrows by; a filter not sent is not
applied. Text filters such as a name or an e-mail match inside the
value, whatever the case. An instant is filtered as a span: …From is on
or after it, …To before it, either alone or both. Every list is newest
first, but a webinar’s sessions, which are in the order they start.
GET /public/v1/webinar-registrations?webinarId=12&createdAtFrom=2026-10-01T00:00:00Z&size=100&page=2Ids and instants
Section titled “Ids and instants”Every id is a whole number. Every instant is an ISO 8601 string in UTC,
2026-11-03T22:00:00.000Z, and is sent the same way — with an offset,
if not Z.
Rate limit
Section titled “Rate limit”Every organization may make 120 requests a minute, over the whole public API, whatever its plan. Each answer says where you stand:
| Header | What it says |
|---|---|
X-RateLimit-Limit |
The limit, 120. |
X-RateLimit-Remaining |
How many are left in this minute. |
X-RateLimit-Reset |
Seconds until the minute turns over. |
Over it, the answer is 429 with TOO_MANY_REQUESTS and a Retry-After
in seconds. Reading a list in pages of 100 stays well under it.