| name | iblai-api-catalog |
| description | Manage an ibl.ai organization's learning catalog via the platform API — courses, programs, pathways, resources, skills, roles, course/program metadata, plus enrollment, eligibility checks, catalog search, and course reviews. Org-wide content and enrollment operations. Use when wiring up the catalog, enrolling users, checking eligibility, or curating skills/roles/pathways. |
iblai-api-catalog
Manage an organization's learning catalog from the API: courses, programs,
pathways, and resources; the skills and roles taxonomy (including each user's
desired/reported skills and roles); course and program metadata; plus
enrollment (course / program / pathway, admin and self), eligibility checks,
catalog search, and course reviews. Use when populating the catalog, enrolling
users, checking who can take what, or curating the skills/roles graph.
Auth & conventions
- Base URL:
https://api.iblai.app/dm — these are Data Manager (DM)
endpoints, so the /dm prefix is required; the /api/catalog/... paths
below are appended to it (e.g. https://api.iblai.app/dm/api/catalog/courses/).
- Header:
Authorization: Api-Token $IBLAI_API_KEY on every request.
- Path vars:
{org} = $IBLAI_ORG (a.k.a. org / platform_key /
platform_org on the wire), {username} = $IBLAI_USERNAME. Org/user are
passed as query params or body fields, not baked into the path.
- DELETE / destructive / outward-facing calls say "Confirm with the user first."
course_id values must be URL-encoded in query strings.
- Not connected yet? Run
/iblai-api-login first to populate IBLAI_ORG,
IBLAI_USERNAME, and IBLAI_API_KEY.
Reads
Courses
- GET
/api/catalog/courses/ — retrieve courses; filter by course_id, slug (case-insensitive), org (query params). Returns [{course_id, name, slug, org}].
Programs
- GET
/api/catalog/programs/ — retrieve programs; filter by program_id, course_id, name, slug, enabled, org (query params). Returns [{program_id, org, slug, name, program_type, platform_key, enabled, course_list}].
Pathways
- GET
/api/catalog/pathways/ — retrieve pathway(s); filter (query params) by pathway_id, pathway_uuid, user_id/username, platform_key, item_id, name, slug (case-insensitive), visible. Returns a (non-paginated) list of pathways, each with a path[] of items.
Resources
- GET
/api/catalog/resources/ — retrieve resources; filter (query params) by id, user_id/username, platform_key/key, org/platform_org, resource_type, name, query (matches name via icontains), item_id. Returns a non-paginated list.
- GET
/api/catalog/resources/search/ — paginated resource search; same filters, page (default 1), page_size (default 50). Results newest-first. Prefer this for large result sets.
Metadata
Course
- GET
/api/catalog/metadata/course/ — read a course's metadata by course_id (query param; the response keys are dynamic, e.g. {subject, tags, level, topics, promotion, slug, ...}). GET /api/catalog/metadata/course/{field}/ reads one metadata field.
- GET
/api/catalog/metadata/course-public/ — read a course's public metadata by course_id (no auth/permission required; ignores course visibility). course-public/{field}/ reads one field. Read-only.
Program
- GET
/api/catalog/metadata/program/ — read a program's metadata; program_id required, optional org (query params). program/{field}/ reads one field.
- GET
/api/catalog/metadata/program-public/ — read a program's public metadata (program_id required, optional org; no auth required). program-public/{field}/ reads one field. Read-only.
Choices
- GET
/api/catalog/metadata/choices/ — query allowed metadata choices; requires field_key or scope (query params), optional org. Returns the choice dict (404 if none).
Skills
- GET
/api/catalog/skills/ — retrieve skills (paginated); filter by id, name, name__iexact, slug, platform_key; sort (default id).
- GET
/api/catalog/skills/desired/ — a user's desired skills by user_id/username (400 if the user has none).
- GET
/api/catalog/skills/reported/ — a user's reported skills by user_id/username (200 with an empty record {"user_id":null,"username":null,"skills":[],"data":null} when there are none).
Roles
- GET
/api/catalog/roles/ — retrieve roles (paginated); filter by id, name, name__iexact, slug, platform_key; sort (default id). Each role embeds its skills[].
- GET
/api/catalog/roles/desired/ — a user's desired roles by user_id/username.
- GET
/api/catalog/roles/reported/ — a user's reported roles by user_id/username.
Eligibility
- GET
/api/catalog/eligibility/courses/ — list courses a user is eligible for; params user_id/username, org, query.
- GET
/api/catalog/eligibility/courses/check/ — check eligibility for one course; course_id required plus user_id or username (course_id URL-encoded), plus org, local_only (skip the remote edX enroll-status call). Always returns {is_eligible}; unless local_only is set, the response is merged with the edX enroll-status fields (e.g. is_enrolled, etc.).
Enrollment
Courses
- GET
/api/catalog/enrollment/courses/search/ — paginated enrollment search; query params (at least one of user_id, username, email, course_id, slug, org, platform_key required) plus course_name (substring), sort (default -id), include_default_platform, include_archived_courses (default false), page, page_size. Returns {count, next_page, previous_page, results[]} of active enrollments.
Programs
- GET
/api/catalog/enrollment/programs/ — query program enrollments; a user identifier (user_id/username) is required (the call 400s on an unresolvable user), and you may also filter by program_id/slug, org/platform_key, program_type (standard|platform|custom), include_metadata (default true), include_default_platform.
- GET
/api/catalog/enrollment/programs/search/ — paginated program-enrollment search; same params as the GET above plus sort, page, page_size. Active enrollments only.
Pathways
- GET
/api/catalog/enrollment/pathways/ — query pathway enrollments; a user identifier (user_id/username) is required, plus optional pathway_id/pathway_uuid/slug, org/platform_key, include_metadata (default true), include_default_platform.
- GET
/api/catalog/enrollment/pathways/search/ — paginated pathway-enrollment search; user identifier required, plus pathway_id/slug, org/platform_key, sort, page, page_size, include_default_platform. Active enrollments only.
Recommendation
- GET
/api/catalog/recommendation/courses/ — get the recommended "next" course relative to a current course. course_id required (query param), plus optional user_id and org. Returns a single serialized course, or null (with 200) when there is no next course.
Reviews
Course reviews
- GET
/api/catalog/reviews/course/ — paginated list of (visible) course reviews; filter (query params) by course_id, user_id, platform_key, platform_org/org, sort (default -id), page, page_size. Returns {count, next_page, previous_page, results[]} where each result is {user_id, username, content, rating, title, visible, created, modified, course_id, metadata}.
- GET
/api/catalog/reviews/course/info/ — aggregate review stats for a course; course_id required (query param). Returns {course_id, avg_rating, count}.
Program reviews
- GET
/api/catalog/reviews/program/ — paginated list of (visible) program reviews; filter by program_id, user_id, platform_key, platform_org/org, sort, page, page_size. Each result includes program_key.
- GET
/api/catalog/reviews/program/info/ — aggregate review stats; program_key required (query param). Returns {program_key, avg_rating, count}.
Writes
Courses
Programs
- POST
/api/catalog/programs/ — create/update a program (200 updated, 201 created). Identify the platform by program_id + (org/platform_key) or by program_key. program_id, name, and course_list are required:
{
"program_id": "string (required)", "name": "string (required)",
"course_list": [{ "course_id": "course-v1:A+B+C" }],
"org": "string", "platform_key": "string", "program_key": "string",
"slug": "string", "enabled": "boolean (default true)",
"program_type": "number (1=standard, 2=platform, 3=custom)",
"data": "object"
}
- DELETE
/api/catalog/programs/ — delete a program by program_id + org (query params, both required). Returns {count, type}. Confirm with the user first.
Pathways
- POST
/api/catalog/pathways/ — create/update a pathway. user_id (required), name (required), and path (required). Use (user_id/username or platform_key) + pathway_id to create; do not send pathway_uuid on create (generated). For an existing pathway, identify by pathway_uuid. Each path[] item is keyed by item_type: resource (resource fields below; created on the fly when no id), course (course_id), program (program_key), or pathway (pathway_id).
{
"user_id": "number (required)", "name": "string (required)",
"username": "string", "platform_key": "string",
"pathway_id": "string", "pathway_uuid": "uuid (update only)",
"slug": "string", "visible": "boolean (default true)",
"path": [
{ "item_type": "resource", "id": "number (omit to create)", "resource_type": "string", "url": "string", "name": "string", "description": "string", "data": "object" },
{ "item_type": "course", "course_id": "course-v1:A+B+C" },
{ "item_type": "program", "program_key": "program-v1:org+id" }
],
"data": "object"
}
Resources
- POST
/api/catalog/resources/ — create/update a resource (omit id to create). Accepts JSON or multipart (for image):
{ "id": "number (update only)", "username": "string", "user_id": "number", "platform_key": "string", "platform_org": "string", "name": "string", "url": "string", "resource_type": "string", "description": "string", "skills": ["string"], "image": "file (multipart)", "data": "object" }
- DELETE
/api/catalog/resources/ — delete a resource; requires id plus user_id or platform_key (query params). Returns {count, type}. Confirm with the user first.
Metadata
Course
- POST
/api/catalog/metadata/course/ — create/update course metadata. course_id and metadata required. With update: true (default) the supplied keys are merged; update: false overwrites. Special keys inside metadata: slug, skills (list of existing skill names). Field-path POSTs (course/{field}/) are not supported (404).
{ "course_id": "string", "update": "boolean (default true)", "metadata": { "subject": "string", "tags": ["string"], "level": "string", "topics": ["string"], "promotion": "string|null", "slug": "string", "skills": ["string"] } }
- POST
/api/catalog/metadata/course-search/ — return course info (to_json()) for courses matching metadata filters in the body, e.g. { "data__contains": {...}, "slug": "string", "course_id": "string" }. Body must be non-empty; invalid filter keys return 400.
Program
- POST
/api/catalog/metadata/program/ — create/update program metadata; program_id required, optional org, plus metadata and update (default true) in the body. Field-path POSTs not supported (404).
Skills
- POST
/api/catalog/skills/ — create/update a skill (omit id to create; platform_key: null for global):
{ "id": "number (update only)", "name": "string", "slug": "string", "platform_key": "string|null", "data": "object" }
- POST
/api/catalog/skills/public/ — create a skill, open to any user (config-gated; names lowercased/trimmed): { "name": "string", "slug": "string", "data": "object" }.
- POST
/api/catalog/skills/desired/ — set a user's desired skills (refer to skills by id):
{ "user_id": "number", "username": "string", "skills": [{ "id": "number" }], "data": "object" }
- POST
/api/catalog/skills/reported/ — set a user's reported skills (same shape as desired).
Roles
- POST
/api/catalog/roles/ — create/update a role (omit id to create):
{ "id": "number (update only)", "name": "string", "slug": "string", "platform_key": "string", "data": "object" }
- POST
/api/catalog/roles/public/ — create a role, open to any user (config-gated; names lowercased/trimmed): { "name": "string", "slug": "string", "data": "object" }.
- POST
/api/catalog/roles/desired/ — set a user's desired roles: { "user_id": "number", "roles": ["string"|{ "id": "number" }], "data": "object" }.
- POST
/api/catalog/roles/reported/ — set a user's reported roles (same shape as desired).
Enrollment
Programs
- POST
/api/catalog/enrollment/programs/ — create/update an enrollment. Requires a user (user_id/username) and a program (program_key or program_id + org/platform_key):
{ "user_id": "number", "username": "string", "program_id": "string", "program_key": "string", "org": "string", "platform_key": "string", "started": "datetime", "expired": "datetime", "active": "boolean (default true)" }
- DELETE
/api/catalog/enrollment/programs/ — deactivate an enrollment (query params: user user_id/username + program program_id/program_key + org/platform_key, optional ignore_expiration default false). Confirm with the user first.
- POST
/api/catalog/enrollment/programs/self/ — self-enrollment (the program must be in a platform the target user belongs to; 403 otherwise). Same body as the admin POST, including user_id/username:
{ "user_id": "number", "username": "string", "program_id": "string", "program_key": "string", "org": "string", "platform_key": "string", "started": "datetime", "expired": "datetime", "active": "boolean (default true)" }
- DELETE
/api/catalog/enrollment/programs/self/ — self-unenroll (same identifiers as the admin DELETE; membership-checked, optional ignore_expiration default false). Confirm with the user first.
Pathways
- POST
/api/catalog/enrollment/pathways/ — create a pathway enrollment; requires a user (user_id/username) and a pathway (pathway_uuid, or pathway_id + org/platform_key):
{ "username": "string", "user_id": "number", "pathway_id": "string", "pathway_uuid": "uuid", "org": "string", "platform_key": "string", "active": "boolean (default true)" }
- DELETE
/api/catalog/enrollment/pathways/ — deactivate a pathway enrollment (same identifiers, query params). Confirm with the user first.
- POST
/api/catalog/enrollment/pathways/self/ — self-enrollment (membership-checked; 403 if the user is not in the pathway's platform). Same body as the admin POST, including user_id/username.
- DELETE
/api/catalog/enrollment/pathways/self/ — self-unenroll (same identifiers, membership-checked). Confirm with the user first.
Search
Reviews
Course reviews
- POST
/api/catalog/reviews/course/update/ — create/update a course review (201 created, 200 updated). course_id and username required (or user_id):
{ "course_id": "string", "username": "string", "user_id": "number", "rating": "number", "title": "string", "content": "string", "visible": "boolean (default true)", "metadata": "object" }
- DELETE
/api/catalog/reviews/course/update/ — delete a user's course review; course_id + username/user_id required (query params). Confirm with the user first.
Program reviews
- POST
/api/catalog/reviews/program/update/ — create/update a program review. program_key and username required (or user_id):
{ "program_key": "program-v1:org+id", "username": "string", "user_id": "number", "rating": "number", "title": "string", "content": "string", "visible": "boolean (default true)", "metadata": "object" }
- DELETE
/api/catalog/reviews/program/update/ — delete a user's program review; program_key + username/user_id required (query params). Confirm with the user first.
Example
Check whether a user is eligible for a specific course (note the URL-encoded course_id):
curl -G \
"https://api.iblai.app/dm/api/catalog/eligibility/courses/check/" \
-H "Authorization: Api-Token $IBLAI_API_KEY" \
--data-urlencode "user_id=36" \
--data-urlencode "org=$IBLAI_ORG" \
--data-urlencode "course_id=course-v1:IBLTEST+IBL000+RUN"
Notes
- All endpoints are DM endpoints served under
https://api.iblai.app/dm (/dm + /api/catalog/...). Omitting the /dm prefix will not resolve.
- Course id format is the opaque-keys form
course-v1:ORG+NUMBER+RUN (e.g. course-v1:IBLTEST+IBL000+RUN). Always URL-encode it in query strings (%3A, %2B).
- Program ids are slug-like strings (e.g.
test-program-000); program_type is a numeric code on write. Resource / skill / role ids are integers; resources also carry a UUID item_id; pathways carry a UUID pathway_uuid (generated on create — never send it on a create call).
- Org on the wire appears as
org, platform_key, or (resource search legacy) platform_org/key — all mean the org key. Pass it as a query param (GET) or body field (POST), not in the path.
- Skills/roles by id, not name. When setting a user's desired/reported skills or roles, reference them by
{"id": …} (recommended) rather than name. Course-metadata skills must reference existing skill names.
- Self vs admin enrollment. Both the non-self and the
…/self/ enrollment endpoints take an explicit user_id/username in the request. The difference is permission scope: …/self/ additionally checks that the target user is a member of the program/pathway's platform (returns 403 if not), so it is the endpoint to use for non-admin (user-token) self-service; the non-self endpoints are for admin tokens enrolling other users.
- Pagination envelope is
{count, next_page, previous_page, results[]} for the search/paginated endpoints (course/program/pathway enrollment search, resource search, skills, roles, course/program review query); plain GETs like resources/ and pathways/ are not paginated.
public/ skill and role creation endpoints are config-gated (ALLOW_PUBLIC_SKILL_CREATE / ALLOW_PUBLIC_ROLE_CREATE) and return 404 when disabled; created names are lowercased and trimmed.
- Auto-increment utility.
GET/POST /api/catalog/increment/ reads/advances per-platform auto-increment numbers (org/key, and number_type on POST). It is an internal numbering helper, not a catalog-management operation — included for completeness only.
- The source repo also ships Django management commands (
convert_slugs_lower, link_item_objects, verify_course_existence); those are server-side operations, not REST endpoints, and are out of scope for this skill.