Bring in a meeting and draft courses, step by step
US Region: https://public-api.sessionboard.com · EU Region: https://public-api-eu.sessionboard.com
"Import last year's meeting and make courses" in three steps. preview (the default) writes nothing: with no appId it lists the platforms and what each brings; with an appId, that platform's events and suggested (the latest one that already happened); with a remoteEventId, what the import would do. import brings the event in, as Bring in a meeting (needs appId and remoteEventId; answers job_id and event). draft makes draft courses from every session of the imported event (needs eventId; pass jobId to get status: still_importing while the import runs), the ones without a recording waiting for one. Nothing is published and no one is notified: publishing is Publish a meeting on demand, which a person approves. Credit is never set here. The token's user needs the Lessons create permission and permission to view integrations. Requires write:learning; refused for a key restricted to particular events. Also at POST /v1/learning/workspace/meetings/import-for-learning.
Request example
curl --request POST \ --url 'https://public-api.sessionboard.com/v1/organization/{orgId}/learning/workspace/meetings/import-for-learning' \ --header 'x-access-token: <api-token>' \ --header 'Content-Type: application/json' \ --data '{ "step": "preview", "appId": "cvent", "remoteEventId": "<string>", "eventId": 123, "jobId": "<string>"}'const response = await fetch('https://public-api.sessionboard.com/v1/organization/{orgId}/learning/workspace/meetings/import-for-learning', { method: 'POST', headers: { "x-access-token": "<api-token>", "Content-Type": "application/json" }, body: JSON.stringify({ "step": "preview", "appId": "cvent", "remoteEventId": "<string>", "eventId": 123, "jobId": "<string>" }),});
const data = await response.json();console.log(data);import requests
response = requests.request( "POST", "https://public-api.sessionboard.com/v1/organization/{orgId}/learning/workspace/meetings/import-for-learning", headers={ "x-access-token": "<api-token>", "Content-Type": "application/json" }, json={ "step": "preview", "appId": "cvent", "remoteEventId": "<string>", "eventId": 123, "jobId": "<string>" },)
print(response.json())<?php
$curl = curl_init();
curl_setopt_array($curl, [ CURLOPT_URL => "https://public-api.sessionboard.com/v1/organization/{orgId}/learning/workspace/meetings/import-for-learning", CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => '{ "step": "preview", "appId": "cvent", "remoteEventId": "<string>", "eventId": 123, "jobId": "<string>"}', CURLOPT_HTTPHEADER => [ "x-access-token: <api-token>", "Content-Type: application/json", ],]);
$response = curl_exec($curl);curl_close($curl);
echo $response;package main
import ( "fmt" "io" "net/http" "strings")
func main() { req, _ := http.NewRequest("POST", "https://public-api.sessionboard.com/v1/organization/{orgId}/learning/workspace/meetings/import-for-learning", strings.NewReader(`{ "step": "preview", "appId": "cvent", "remoteEventId": "<string>", "eventId": 123, "jobId": "<string>"}`)) req.Header.Add("x-access-token", "<api-token>") req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))}HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://public-api.sessionboard.com/v1/organization/{orgId}/learning/workspace/meetings/import-for-learning")) .header("x-access-token", "<api-token>") .header("Content-Type", "application/json") .method("POST", HttpRequest.BodyPublishers.ofString("{\n \"step\": \"preview\",\n \"appId\": \"cvent\",\n \"remoteEventId\": \"<string>\",\n \"eventId\": 123,\n \"jobId\": \"<string>\"\n}")) .build();
HttpResponse<String> response = HttpClient.newHttpClient() .send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());Try it
Response headers
Authorizations
x-access-tokenstringheaderOrganization API token. Generate from Organization Settings → API Tokens.
AuthorizationBearer <token>headerorOAuth 2.1 access token. Obtained via the OAuth PKCE flow at
/oauth/token.
Send one of these. See Authentication.
Path parameters
orgIdstringpathrequiredYour organization ID. Any other organization returns
404.
Request body
stepstring- Allowed values
"preview", "import", "draft"- Default
"preview"
appIdstringA registration platform. Today sessions can be brought in from
cvent,swoogoandbizzabo; the others answernot_available(List registration platforms says why).- Allowed values
"cvent", "swoogo", "bizzabo", "rainfocus", "eventbrite", "swapcard", "visit", "map-your-show", "a2z"
remoteEventIdstringThe platform's event id.
- Max length
200
eventIdinteger | stringThe Sessionboard event the import made (
draftstep).Option 1
integer
Option 2
string
jobIdstringThe import job (
draftstep waits for it).- Max length
64
{ "step": "preview", "appId": "cvent", "remoteEventId": "<string>", "eventId": 123, "jobId": "<string>"}Responses
200application/json
The step's answer: step plus, for preview, the platforms (as List registration platforms), one platform's events (as List a registration platform's events, with suggested and message) or an import preview (as Bring in a meeting with status: preview); for import, the import (as Bring in a meeting); for draft, status: still_importing or status: drafted with the result of Make draft courses from a meeting and next.
successbooleanpayloadLearningMeetingForLearningStepstepplus the fields of the answer it wraps (List registration platforms, List a registration platform's events, Bring in a meeting, or Make draft courses from a meeting).Show child attributes
stepstring- Allowed values
"preview", "import", "draft"
statusstringstill_importingordraftedon thedraftstep; onimportand an import preview, as in Bring in a meeting.suggestedLearningRemoteEvent | any | nullpreviewwith anappId: the latest of its events that already happened.Show child attributes
idstringThe platform's event id.
namestringstarts_atstring | nullimported_event_idinteger | nullThe Sessionboard event it was brought into before.
imported_event_namestring | null
event_idintegerstill_importingonly.nextstringdraftedonly: what to do next.messagestring
400application/json
The body failed validation; Importing needs appId and remoteEventId.; Drafting needs the eventId the import returned.; the connection has no event with that id; or No courses could be made from those sessions.
Gateway errors carry error (a code) and message. Errors from Learning itself carry status, success: false, message, name, and sometimes code (and feature or paused_at).
errorstring | objectThe gateway's error code (
SCOPE_REQUIRED,ORG_WIDE_TOKEN_REQUIRED,NOT_FOUND, …).messagestringstatusintegersuccessbooleannamestringcodestringFEATURE_NOT_ENABLED,AGENT_WRITES_PAUSED, …featurestringpaused_atstring<date-time>
401
Missing, invalid or expired token.
403application/json
SCOPE_REQUIRED— the token lacksread:learning(reads) orwrite:learning(writes). Legacy tokens with no scopes cannot write.ORG_WIDE_TOKEN_REQUIRED— the token is restricted to particular events: "Bringing in a meeting reaches the organization's registration platforms and every event, so this API key (restricted to particular events) cannot use it. Use a key without an event restriction."FEATURE_NOT_ENABLED(feature: lessons_credits) — Learning is not on for the organization.FORBIDDEN— the token's user is not an active member of the organization, lacks the Lessons permission, or (listing a platform's events, importing) lacks permission to view integrations (You need permission to view integrations to use Apps).
Gateway errors carry error (a code) and message. Errors from Learning itself carry status, success: false, message, name, and sometimes code (and feature or paused_at).
errorstring | objectThe gateway's error code (
SCOPE_REQUIRED,ORG_WIDE_TOKEN_REQUIRED,NOT_FOUND, …).messagestringstatusintegersuccessbooleannamestringcodestringFEATURE_NOT_ENABLED,AGENT_WRITES_PAUSED, …featurestringpaused_atstring<date-time>
404application/json
Another organization, or (draft step) the event is not in your organization (Event could not be found).
Gateway errors carry error (a code) and message. Errors from Learning itself carry status, success: false, message, name, and sometimes code (and feature or paused_at).
errorstring | objectThe gateway's error code (
SCOPE_REQUIRED,ORG_WIDE_TOKEN_REQUIRED,NOT_FOUND, …).messagestringstatusintegersuccessbooleannamestringcodestringFEATURE_NOT_ENABLED,AGENT_WRITES_PAUSED, …featurestringpaused_atstring<date-time>
429application/json
- The token's request limit (100 requests per 15 minutes per bucket by default — see Rate Limiting). Wait
Retry-Afterseconds. QUOTA_EXCEEDED(writes) — the token's daily write quota (10,000 a day). Resets at midnight UTC.
Gateway errors carry error (a code) and message. Errors from Learning itself carry status, success: false, message, name, and sometimes code (and feature or paused_at).
errorstring | objectThe gateway's error code (
SCOPE_REQUIRED,ORG_WIDE_TOKEN_REQUIRED,NOT_FOUND, …).messagestringstatusintegersuccessbooleannamestringcodestringFEATURE_NOT_ENABLED,AGENT_WRITES_PAUSED, …featurestringpaused_atstring<date-time>
Retry-AfterintegerheaderSeconds to wait before retrying.
Response examples
{ "success": true, "payload": { "step": "preview", "status": "<string>", "suggested": { "id": "<string>", "name": "<string>", "starts_at": "<string>", "imported_event_id": 123, "imported_event_name": "<string>" }, "event_id": 123, "next": "<string>", "message": "<string>" }}{ "error": "<string>", "message": "<string>", "status": 123, "success": true, "name": "<string>", "code": "<string>", "feature": "<string>", "paused_at": "2026-01-15T09:30:00Z"}{ "error": "ORG_WIDE_TOKEN_REQUIRED", "message": "Bringing in a meeting reaches the organization's registration platforms and every event, so this API key (restricted to particular events) cannot use it. Use a key without an event restriction."}{ "error": "<string>", "message": "<string>", "status": 123, "success": true, "name": "<string>", "code": "<string>", "feature": "<string>", "paused_at": "2026-01-15T09:30:00Z"}{ "error": "<string>", "message": "<string>", "status": 123, "success": true, "name": "<string>", "code": "<string>", "feature": "<string>", "paused_at": "2026-01-15T09:30:00Z"}