Get one learner's engagement
US Region: https://public-api.sessionboard.com · EU Region: https://public-api-eu.sessionboard.com
One person across every product: the score (Learning's view and overall) with its parts and why, a timeline across meetings, campaigns and courses, credit owed this cycle against the credit goal, certifications coming up for renewal, the next three courses with the reason for each, and their events and Marketing activity. A teammate limited to some credits portfolios gets 404 for anyone outside them. Reads only. Requires read:learning; refused for a key restricted to particular events. Also at GET /v1/learning/workspace/engagement/learners/{personId}.
Request example
curl --request GET \ --url 'https://public-api.sessionboard.com/v1/organization/{orgId}/learning/workspace/engagement/learners/{personId}' \ --header 'x-access-token: <api-token>'const response = await fetch('https://public-api.sessionboard.com/v1/organization/{orgId}/learning/workspace/engagement/learners/{personId}', { method: 'GET', headers: { "x-access-token": "<api-token>" },});
const data = await response.json();console.log(data);import requests
response = requests.request( "GET", "https://public-api.sessionboard.com/v1/organization/{orgId}/learning/workspace/engagement/learners/{personId}", headers={ "x-access-token": "<api-token>" },)
print(response.json())<?php
$curl = curl_init();
curl_setopt_array($curl, [ CURLOPT_URL => "https://public-api.sessionboard.com/v1/organization/{orgId}/learning/workspace/engagement/learners/{personId}", CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "x-access-token: <api-token>", ],]);
$response = curl_exec($curl);curl_close($curl);
echo $response;package main
import ( "fmt" "io" "net/http")
func main() { req, _ := http.NewRequest("GET", "https://public-api.sessionboard.com/v1/organization/{orgId}/learning/workspace/engagement/learners/{personId}", nil) req.Header.Add("x-access-token", "<api-token>")
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/engagement/learners/{personId}")) .header("x-access-token", "<api-token>") .method("GET", HttpRequest.BodyPublishers.noBody()) .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.personIdstring<uuid>pathrequiredThe People id (from Find a learner or Rank learners by engagement).
Responses
200application/json
OK
successbooleanpayloadobjectShow child attributes
learnerLearningEngagementLearnerLearning's view of the one engagement score (learning counts more), with the overall score beside it.
Show child attributes
person_idstring<uuid>namestringemailstringscoreinteger- Minimum
0- Maximum
100
bandstringwarming(Warming up),engaged(Engaged),highly(Highly engaged).- Allowed values
"warming", "engaged", "highly"
band_labelstringwhystringThe score as a sentence, e.g.
72 = 3 courses · 4.5 credits · certified · 2 webinars.overallobjectShow child attributes
scoreinteger- Minimum
0- Maximum
100
bandstringwarming(Warming up),engaged(Engaged),highly(Highly engaged).- Allowed values
"warming", "engaged", "highly"
whystring
courses_completedintegercourses_startedintegercreditsnumbercertificationsintegerpartsobject[]What makes up the score.
Show child attributes
keystringThe activity, e.g.
courses,credits,certified,events,webinars.countintegerpointsintegersentintegerEmails sent
amountnumberFor credit.
productstring- Allowed values
"platform", "marketing", "learning"
linesLearningEngagementLinesThe scores where the bands start (default 50 and 80).
Show child attributes
engagednumberhighlynumber
timelineobject[]Show child attributes
typestringatstring<date-time>textstringeventstring | nullsourcestring | nullcontent_idstring | null
credit_owedobject | nullCredit owed this cycle against the credit goal.
nullwithout a goal.Show child attributes
goalnumberearnednumberowednumbercredit_typestring | nullbystring<date-time> | nullcycle_startstring<date-time>cycle_endstring<date-time> | null
renewalsobject[]Show child attributes
certification_idstring<uuid>namestringexpires_atstring<date-time>days_leftinteger
next_lessonsLearningNextLesson[]- Max items
3
Show child attributes
lesson_idstring<uuid>content_idstringtitlestringkindstringminutesinteger | nullcreditobject[]Show child attributes
type_idstring<uuid> | nullnamestring | nullamountnumber
eventstring | nullsessionstring | nullreasonstring- Allowed values
"renewal", "continue", "attended", "topic", "credit", "popular"
becausestringrankintegerearns_creditbooleanattendedonly.
activityobjectShow child attributes
events_attendedintegerwebinars_watchedintegersessions_attendedintegercampaigns_openedintegerclips_watchedintegersharedintegerlast_atstring<date-time> | null
400application/json
A path, query or body value failed validation, or an unknown body property was sent. message names the field. (A source object naming the assistant, with the person's prompt, is accepted on every write and removed before validation.) For an {eventId} path that is not a whole number: error: VALIDATION_ERROR, eventId must be a valid integer.
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: "The Learning workspace covers every event and learner in the organization, 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, or lacks the Lessons permission the operation needs.
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
No such person in your organization or portfolios, or they have no email (Learner could not be found), or another organization.
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": { "learner": { "person_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "name": "<string>", "email": "<string>", "score": 0, "band": "warming", "band_label": "<string>", "why": "<string>", "overall": { "score": 0, "band": "warming", "why": "<string>" }, "courses_completed": 123, "courses_started": 123, "credits": 123.45, "certifications": 123, "parts": [ { "key": "<string>", "count": 123, "points": 123, "sent": 123, "amount": 123.45, "product": "platform" } ], "lines": { "engaged": 123.45, "highly": 123.45 }, "timeline": [ { "type": "<string>", "at": "2026-01-15T09:30:00Z", "text": "<string>", "event": "<string>", "source": "<string>", "content_id": "<string>" } ], "credit_owed": { "goal": 123.45, "earned": 123.45, "owed": 123.45, "credit_type": "<string>", "by": "2026-01-15T09:30:00Z", "cycle_start": "2026-01-15T09:30:00Z", "cycle_end": "2026-01-15T09:30:00Z" }, "renewals": [ { "certification_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "name": "<string>", "expires_at": "2026-01-15T09:30:00Z", "days_left": 123 } ], "next_lessons": [ { "lesson_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "content_id": "<string>", "title": "<string>", "kind": "course", "minutes": 123, "credit": [ { "type_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "name": "<string>", "amount": 123.45 } ], "event": "<string>", "session": "<string>", "reason": "renewal", "because": "<string>", "rank": 123, "earns_credit": true } ], "activity": { "events_attended": 123, "webinars_watched": 123, "sessions_attended": 123, "campaigns_opened": 123, "clips_watched": 123, "shared": 123, "last_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"}{ "error": "ORG_WIDE_TOKEN_REQUIRED", "message": "The Learning workspace covers every event and learner in the organization, so this API key (restricted to particular events) cannot use it. Use a key without an event restriction."}{ "error": "SCOPE_REQUIRED", "message": "This operation requires the 'write:learning' scope."}{ "status": 403, "success": false, "message": "Feature 'lessons_credits' is not enabled for this organization", "name": "FeatureNotEnabledError", "code": "FEATURE_NOT_ENABLED", "feature": "lessons_credits"}{ "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"}