Remove a buyer's access
US Region: https://public-api.sessionboard.com · EU Region: https://public-api-eu.sessionboard.com
Ends the learner's access to the order's course. The sale stays on record. A refund in the payment gateway keeps access until this is called. Waits for a person's OK (202 needs_approval). Needs the permission that manages plan and billing, or an organization admin (403 otherwise). Requires write:learning. Also at POST /v1/learning/workspace/sales/{orderId}/remove-access.
Request example
curl --request POST \ --url 'https://public-api.sessionboard.com/v1/organization/{orgId}/learning/workspace/sales/{orderId}/remove-access' \ --header 'x-access-token: <api-token>'const response = await fetch('https://public-api.sessionboard.com/v1/organization/{orgId}/learning/workspace/sales/{orderId}/remove-access', { method: 'POST', headers: { "x-access-token": "<api-token>" },});
const data = await response.json();console.log(data);import requests
response = requests.request( "POST", "https://public-api.sessionboard.com/v1/organization/{orgId}/learning/workspace/sales/{orderId}/remove-access", 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/sales/{orderId}/remove-access", CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => "POST", 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("POST", "https://public-api.sessionboard.com/v1/organization/{orgId}/learning/workspace/sales/{orderId}/remove-access", 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/sales/{orderId}/remove-access")) .header("x-access-token", "<api-token>") .method("POST", 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.orderIdstring<uuid>pathrequiredThe order id (from List course sales).
Responses
202application/json
Waiting for a person. Nothing was published or sent: a person approves or declines the request in Sessionboard Learning (payload.url), and it then runs as them. Do not call again.
successbooleanpayloadLearningApprovalRequestShow child attributes
statusstringapproval_idstring<uuid>urlstringWhere a person approves or declines it, in Sessionboard Learning.
messagestringWaiting for your OK in Sessionboard: <url>notestringSays nothing was sent or published and not to call again.
approvalLearningApprovalShow child attributes
idstring<uuid>statusstring- Allowed values
"pending", "approved", "declined", "failed"
actionstringpublish_course,publish_on_demandorpublish_course_draft.surfacestringcoursesfor these operations.titlestringThe approval card's headline, e.g.
Publish the course “Intro to Safety”.summarystringWhat the person asked the assistant, when given (
From “…”), else empty.targetobject | nullShow child attributes
typestringcourse,eventorcourse_draft.idstring
event_idinteger | nullassistantobjectShow child attributes
vendorstringlabelstringclientstring | nullviastring | null- Allowed values
"api_token", "oauth", null
requested_byobjectShow child attributes
user_idinteger | nullnamestring | null
decided_byobject | nullShow child attributes
user_idintegernamestring | null
decided_atstring<date-time> | nullerrorstring | nullremedyobject | nullSet only when a run failed for a reason a person can fix in one step.
can_retrybooleancreated_atstring<date-time>productstringurlstring
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
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>
423application/json
A person has paused connected assistants for the organization or the event (code: AGENT_WRITES_PAUSED). Ask them to resume it in Sessionboard before trying again.
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": { "status": "needs_approval", "approval_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "url": "<string>", "message": "<string>", "note": "<string>", "approval": { "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "status": "pending", "action": "<string>", "surface": "<string>", "title": "<string>", "summary": "<string>", "target": { "type": "<string>", "id": "<string>" }, "event_id": 123, "assistant": { "vendor": "<string>", "label": "<string>", "client": "<string>", "via": "api_token" }, "requested_by": { "user_id": 123, "name": "<string>" }, "decided_by": { "user_id": 123, "name": "<string>" }, "decided_at": "2026-01-15T09:30:00Z", "error": "<string>", "remedy": {}, "can_retry": true, "created_at": "2026-01-15T09:30:00Z", "product": "learning", "url": "<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": "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": "NOT_FOUND", "message": "Organization not found"}{ "status": 423, "success": false, "message": "A person has paused connected assistants in Sessionboard. Ask them to resume it from their workspace before trying again.", "name": "AgentWritesPausedError", "code": "AGENT_WRITES_PAUSED", "paused_at": "2026-11-06T15:04:05.000Z"}{ "error": "<string>", "message": "<string>", "status": 123, "success": true, "name": "<string>", "code": "<string>", "feature": "<string>", "paused_at": "2026-01-15T09:30:00Z"}