Publish and assign a course draft
US Region: https://public-api.sessionboard.com · EU Region: https://public-api-eu.sessionboard.com
Publishes the draft's lessons, course and certification to every learner in the organization. Lessons upsert by key, so publishing an edited draft again updates the same lessons and keeps learners' progress. With assign, assigns the certification (or the course when there is none) and messages each assignee (Slack DM, or email when Slack can't reach them); repeating the same assign does not assign or message again. With announce.slackChannelId, posts the announcement in that channel. Refused while clips are still being cut unless allowPendingMedia. The token's user needs the Lessons create and update permissions. Requires write:learning. Also at POST /v1/learning/drafts/{draftId}/apply.
Request example
curl --request POST \ --url 'https://public-api.sessionboard.com/v1/organization/{orgId}/learning/drafts/{draftId}/apply' \ --header 'x-access-token: <api-token>' \ --header 'Content-Type: application/json' \ --data '{ "assign": { "allTeam": true, "userIds": [ 123 ], "dueInDays": 1, "required": true }, "announce": { "slackChannelId": "<string>" }, "allowPendingMedia": false}'const response = await fetch('https://public-api.sessionboard.com/v1/organization/{orgId}/learning/drafts/{draftId}/apply', { method: 'POST', headers: { "x-access-token": "<api-token>", "Content-Type": "application/json" }, body: JSON.stringify({ "assign": { "allTeam": true, "userIds": [ 123 ], "dueInDays": 1, "required": true }, "announce": { "slackChannelId": "<string>" }, "allowPendingMedia": false }),});
const data = await response.json();console.log(data);import requests
response = requests.request( "POST", "https://public-api.sessionboard.com/v1/organization/{orgId}/learning/drafts/{draftId}/apply", headers={ "x-access-token": "<api-token>", "Content-Type": "application/json" }, json={ "assign": { "allTeam": True, "userIds": [ 123 ], "dueInDays": 1, "required": True }, "announce": { "slackChannelId": "<string>" }, "allowPendingMedia": False },)
print(response.json())<?php
$curl = curl_init();
curl_setopt_array($curl, [ CURLOPT_URL => "https://public-api.sessionboard.com/v1/organization/{orgId}/learning/drafts/{draftId}/apply", CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => '{ "assign": { "allTeam": true, "userIds": [ 123 ], "dueInDays": 1, "required": true }, "announce": { "slackChannelId": "<string>" }, "allowPendingMedia": false}', 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/drafts/{draftId}/apply", strings.NewReader(`{ "assign": { "allTeam": true, "userIds": [ 123 ], "dueInDays": 1, "required": true }, "announce": { "slackChannelId": "<string>" }, "allowPendingMedia": false}`)) 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/drafts/{draftId}/apply")) .header("x-access-token", "<api-token>") .header("Content-Type", "application/json") .method("POST", HttpRequest.BodyPublishers.ofString("{\n \"assign\": {\n \"allTeam\": true,\n \"userIds\": [\n 123\n ],\n \"dueInDays\": 1,\n \"required\": true\n },\n \"announce\": {\n \"slackChannelId\": \"<string>\"\n },\n \"allowPendingMedia\": false\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.draftIdstring<uuid>pathrequired
Request body
assignobjectShow child attributes
allTeambooleanEveryone on the team, including people who join later.
userIdsinteger[]dueInDaysinteger | null- Minimum
1- Maximum
365
requiredboolean- Default
true
announceobjectShow child attributes
slackChannelIdstring- Max length
32
allowPendingMediaboolean- Default
false
{ "assign": { "allTeam": true, "userIds": [ 123 ], "dueInDays": 1, "required": true }, "announce": { "slackChannelId": "<string>" }, "allowPendingMedia": false}Responses
200
Published; the draft with apply_result (diff, the assignment and its delivery report).
400
A clip could not be cut, or there is nothing to assign.
403
Token lacks write:learning, the user lacks the Lessons permissions, clips are still being cut, or the draft changed or is being published (reload it).
