The resources the public API exposes
Prerequisite: an active API key, see API keys.
The resources the public API exposes
Prerequisite: an active API key, see API keys.
Permissions required: none in the back office. The caller is the account, not a person: the token carries the admin scope and reaches everything inside that account.
This page states which resources exist, under which paths, and which of them accept a write. Token mechanics live on Authenticating on the API. The full OpenAPI specification, with schemas and examples, is published at doc.developers.beedeez.com and downloadable as openapi.json.
⚠️ api.developers.beedeez.com is the API server, not the documentation: its root returns 404.
Shared conventions
- Base:
https://api.developers.beedeez.com, over HTTPS,application/jsonin and out, request bodies capped at 25 MB. - Version: everything sits under
/v1. One version is in service. - Identifiers: Beedeez identifiers are 24-character hexadecimal strings.
- Dates: use ISO 8601 for every date you send. It is the only format to rely on.
The resources
| Resource | What it exposes | Paths under /v1 |
|---|---|---|
| Tokens | Exchanging the key for a token, the only entries open without one | POST /token, POST /token/refresh |
| Users | Learner accounts, their groups and their notifications for reading, plus revoking one learner’s token | GET /users, /users/email/{email}, /users/externalId/{externalId}, /users/{userId}/groups, /users/{userId}/notifications, POST /auth/logout-by-id |
| Groups | Groups and their members, read-only | GET /groups, /groups/{groupId}, /groups/{groupId}/users, /groups/name/{uniqueName}, /groups/name/{uniqueName}/users |
| Capsules | Capsules, readable and creatable | GET /lessons, /lessons/{ID}, POST /lessons/create |
| Tracks and categories | Tracks and the classification tree, read-only | GET /tracks, GET /categories |
| Activity | One learner’s progress on one capsule, read-only | GET /active-lessons, /users/{USER_ID}/active-lessons, /lessons/{LESSON_ID}/active-lessons, /users/{USER_ID}/lessons/{LESSON_ID}/active-lessons |
| Answers | The question-by-question detail, read-only | GET /users/{USER_ID}/answers, /lessons/{LESSON_ID}/answers, /users/{USER_ID}/lessons/{LESSON_ID}/answers |
| Sessions | Sessions and their registrations, readable and writable | GET and POST /lesson-session, GET and PUT /lesson-session/{ID}, POST /lesson-session/{ID}/register/{USER_ID}, DELETE /lesson-session/{ID}/unregister/{USER_ID}, GET /lesson-session/{USER_ID}/registrations |
| Callbacks | Completion reported back by a third-party tool, writable | POST and GET /callbacks/update-user-lesson-status/{CALLBACK_TOKEN} |
These entries are one single API, the one the specification describes. Webhooks are a separate mechanism, where Beedeez calls your URL.
Pagination, filters and sorting
Two parameters wherever pagination exists: pageSize and pageNumber, the first page being 1. The rules differ by resource. Capsules, activity and answers cap pageSize at 500 and fall back to 50 when it is omitted, an out-of-range value returning 400. Users, groups and notifications have no cap: without pageSize, the size comes from a server-side setting whose value is not public, so pass it explicitly. Tracks, categories and sessions are not paginated and return the whole account in one call.
The search parameter does not look at the same fields everywhere:
- on
GET /v1/users, it matches the first name, the last name, the email and the login; - on the two entries that list a group’s members, it matches those four fields and the alias;
- on
GET /v1/groups, it matches the group’s title, unique name and description, not the names of its members.
The other filters: includeDisabled=true brings back deactivated accounts and disabled groups, both excluded by default; updatedSince on activity and answers returns only what moved since a given date, which is what an incremental sync runs on; includeArchived and includeEntryQuiz add previous attempts and the entry quiz; since, seen and includeBackOffice filter notifications. There is no sort parameter, order is fixed per resource.
Scoping to your account
Every authenticated call is filtered on the account carried by the token: an identifier belonging to another account returns 404 or an empty list, never the data. The two callbacks are the exception and require no access token at all. Their only guarantee is the callback token inside the URL, which carries the account, the learner and the capsule. Treat that URL as a secret, exactly like a key.
Errors
A business error returns a three-field JSON body:
{ "message": "Group not found", "kind": "DomainError", "statusCode": 404 }A rejected validation returns 422 with message and a details object; a server error returns 500 with message alone. The codes in service: 400 invalid parameter, 401 token missing, expired or out of scope, 403 access denied, 404 not found, 422 validation, 500 server error.
What it does not do
No writes on users, groups, tracks or categories. Creating or changing a learner goes through provisioning.
No total count. A response is a bare array: no total, no page count, no link to the next page. An empty page is the only end-of-data signal.
GET /v1/lessons/{ID}/ranking returns no ranking. The entry is in the specification and answers 200 with a text string carrying no data.
No rate limit is published, and none is enforced today. Do not build anything on that absence.
Traps to watch for
Answer pagination counts activity records, not answers. A page of pageSize activity records flattens into many more rows: the number of items you receive is never the number you asked for.
GET /v1/groups/{groupId}/users does not check that the group is yours, unlike GET /v1/groups/{groupId}. The documented 404 never fires, a foreign identifier returns an empty list. Do not use this entry to test whether a group exists.
POST /v1/auth/logout-by-id expects the learner’s external identifier, the one from your HR system, not their Beedeez identifier.
Going further
- Authenticating on the API: getting the token and handling expiry, the first thing to write
- API keys: the key is shown once and once only, read before you click
- The completion callback: the only use for the two callback entries above
- Webhook events: the list of events actually emitted, shorter than you would guess
- API, webhooks, callbacks: which to choose: worth rereading if the mechanism is not yet settled