eWebinar developer documentation
Five ways to work with eWebinar programmatically. Pick the one that matches what you are building.
Each of these opens once you are signed in to your eWebinar account.
REST API v2
Read and manage webinars, registrants and conversations from your own systems over HTTP.
For backend developers building an in-house integration.
MCP server
Connect Cursor, Claude or ChatGPT to an eWebinar account so an assistant can read your webinars and edit drafts.
For customers using AI assistants.
Webhooks
Be notified the moment someone registers, attends, converts or unsubscribes, with a signed payload you can verify.
For automation and CRM sync.
Chatbot provider API
The endpoints your service implements so eWebinar can use your chatbot as an AI moderator in webinar chat.
For chatbot vendors, not eWebinar customers.
JavaScript API
Control embedded eWebinar widgets from your own page — cookie consent and registration callbacks.
For front-end developers.
Getting started
Everything on this page applies to the eWebinar REST API v2 and, because the MCP server is a thin adapter over it, to the MCP tools as well.
Base URLs
| Surface | Base URL |
|---|---|
| REST API v2 | https://api.ewebinar.com/v2 |
| MCP server | https://api.ewebinar.com/mcp |
| Webhooks | Your endpoint — eWebinar calls you |
| Chatbot provider API | Your service, configured per team (e.g. https://api.yourservice.com) |
| JavaScript API | Runs in the visitor's browser, loaded by the eWebinar embed snippet |
Create an API key
- Open team settings → integrations in the eWebinar app.
- Add the API access integration, or open it if you already have it.
- Click new key, name it, tick the permissions it needs under what it can do, then create key and copy it. The key is shown once.
Send the key as a bearer token on every request:
Authorization: Bearer <your-api-key>
An API key belongs to the team, not to a person, and it is not tied to a login session. If you need per-user tokens instead, mint an OAuth access token — see the MCP reference for the authorization flow, which is the same flow for plain REST use.
For the chatbot provider API the direction is reversed: eWebinar sends your service the API key that the team configured, as a bearer token.
Permissions
A credential carries the permissions it was granted when it was created, and nothing else. For an API key those are the boxes you tick on the create form; for an OAuth token they are the boxes the person ticks on the consent screen. It is one list either way:
| Permission | What it allows |
|---|---|
| Read | Read eWebinars, their settings, sessions, transcripts and analytics |
| Edit drafts | Create and edit drafts, and upload media |
| Publish | Publish and unpublish, and change settings that are live immediately |
| Integrations | Connect and manage the team's integrations |
| Registrants | Read registrants, register attendees, manage email allow-lists |
| Delete registrants | Delete a registrant |
Read is always granted — every credential can read. The others are independent, so a key with only Read and Registrants can add a registrant but cannot touch a draft. An OAuth consent screen offers only the permissions the person signing in holds themselves, so somebody who cannot manage integrations cannot grant that to an app.
Every route in the REST reference and every tool in the
MCP reference names the permission it needs. A request with a valid credential that
was not granted that permission fails with 403 FORBIDDEN, not 401.
Two limits are not permissions and cannot be granted:
- First publish needs a signed-in person, because it can start billing. An API key can publish a webinar that has been published before.
- GraphQL is closed to API credentials entirely. REST v2 and the MCP server are the supported surfaces for machines.
Pagination
List endpoints use cursor-based pagination:
- The first request omits the
nextCursorparameter. - If the response includes a
nextCursorvalue, pass it on the next request to get the next page. - When
nextCursoris absent ornull, you have reached the last page.
{
"webinars": [...],
"nextCursor": "ah0s976dhs"
}
Cursors are opaque. Do not construct or parse them.
Errors
Errors share one JSON envelope:
{
"errors": [
{
"message": "Human-readable description",
"code": "ERROR_CODE"
}
]
}
Branch on code, not on message.
| Code | HTTP status | Description |
|---|---|---|
BAD_USER_INPUT |
400 | Invalid request parameters |
GRAPHQL_VALIDATION_FAILED |
400 | Request validation failed |
SESSION_EXPIRED |
400 | The requested session time has passed |
SESSION_IS_FULL |
400 | The session has reached capacity |
SESSION_DURING_BLACKOUT |
400 | The session falls within a blackout period |
UNAUTHENTICATED |
401 | Missing or invalid authentication |
FORBIDDEN |
403 | The credential is valid but was not granted the required permission |
NOT_FOUND |
404 | Resource not found |
RATE_LIMIT_EXCEEDED, TOO_MANY_REQUESTS |
429 | A rate limit was exceeded; see below |
UNKNOWN_ERROR |
500 | Internal server error |
Rate limits
Requests are rate limited per minute, per client address and per operation. API keys and integrations also have a daily ceiling of 10,000 requests per operation per team, counted over the UTC calendar day and reset at 00:00 UTC — a bulk load larger than that against one operation spans UTC days, so spread it or ask us to raise the ceiling.
An exceeded limit returns 429 with the same envelope, with code RATE_LIMIT_EXCEEDED or TOO_MANY_REQUESTS (treat them alike), a Retry-After header and, in extensions, retryAfterSeconds and resetAt (ISO 8601) so a client can wait for the exact moment rather than polling. For a full read of /v2/registrants the refusal names updatedSince, which is the supported way to keep a copy in sync and is limited far less than paging the whole list.