List certifications
US Region: https://public-api.sessionboard.com · EU Region: https://public-api-eu.sessionboard.com
Every certification in the organization (draft, published and retired), by name, with its required lessons and courses, how many lessons it takes and their total minutes, how many people hold it now, how many awards expire within 30 days, and how many people are assigned it and overdue. Reads only. The token's user needs the Lessons read permission. Requires read:learning. Also at GET /v1/learning/certifications.
Request example
curl --request GET \ --url 'https://public-api.sessionboard.com/v1/organization/{orgId}/learning/certifications' \ --header 'x-access-token: <api-token>'const response = await fetch('https://public-api.sessionboard.com/v1/organization/{orgId}/learning/certifications', { 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/certifications", 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/certifications", 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/certifications", 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/certifications")) .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.
Responses
200application/json
OK
successbooleanpayloadobjectShow child attributes
certificationsLearningCertification[]Show child attributes
idstring<uuid>org_idstring<uuid>slugstring | nullnamestringsummarystring | nullbadge_colorstring | nullrequirementsobject[]Lessons and courses (series) that must be completed.
Show child attributes
kindstring- Allowed values
"lesson", "series"
idstring<uuid>
validity_monthsinteger | nullHow long an award lasts.
nullnever expires.versionintegerstatusstring- Allowed values
"draft", "published", "retired"
external_keystring | nullcreated_atstring<date-time>updated_atstring<date-time>lesson_countintegerLessons it takes, courses expanded.
duration_minutesintegerTotal minutes of those lessons.
holdersintegerPeople holding it now (active, not expired).
expiringintegerAwards expiring within 30 days.
assignedintegerPeople assigned it.
overdueintegerAssigned people past their due date.
401
Missing, invalid or expired token.
403
SCOPE_REQUIRED— the token lacksread:learning(reads) orwrite:learning(writes). Legacy tokens with no scopes cannot write.FORBIDDEN— Learning is not on for the organization, or the token's user lacks the Lessons permission.
404application/json
orgId is not your organization (error: NOT_FOUND, message: Organization not 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": { "certifications": [ { "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "org_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "slug": "<string>", "name": "<string>", "summary": "<string>", "badge_color": "<string>", "requirements": [ { "kind": "lesson", "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a" } ], "validity_months": 123, "version": 123, "status": "draft", "external_key": "<string>", "created_at": "2026-01-15T09:30:00Z", "updated_at": "2026-01-15T09:30:00Z", "lesson_count": 123, "duration_minutes": 123, "holders": 123, "expiring": 123, "assigned": 123, "overdue": 123 } ] }}{ "error": "NOT_FOUND", "message": "Organization not found"}{ "error": "<string>", "message": "<string>", "status": 123, "success": true, "name": "<string>", "code": "<string>", "feature": "<string>", "paused_at": "2026-01-15T09:30:00Z"}