Administer an ibl.ai organization via the platform API - manage Users (list, activate, promote/demote, bulk role sync, set policies), edX roles (full catalog: global/course/org), Groups, RBAC Roles and Policies, Teams (user-groups + team access), and Alerts (watched groups/users/watchers). Use for organization-level user and access administration.
Installs into .claude/skills of the current project.
Are you the author of Iblai Api Management?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/iblai-iblai-api-management)
---
name: iblai-api-management
description: Administer an ibl.ai organization via the platform API - manage Users (list, activate, promote/demote, bulk role sync, set policies), edX roles (full catalog: global/course/org), Groups, RBAC Roles and Policies, Teams (user-groups + team access), and Alerts (watched groups/users/watchers). Use for organization-level user and access administration.
metadata:
kind: api
---
# iblai-api-management
Administer an organization from the API: manage **Users, Groups, Roles,
Policies, Teams, and Alerts** for organization-level user and access
administration.
## Auth & conventions
- **Base URL:** `https://api.iblai.app`
- **Header:** `Authorization: Api-Token $IBLAI_API_KEY` on every request.
- **Path vars:** `{org}` = `$IBLAI_ORG` (a.k.a. `platform_key`),
`{username}` = `$IBLAI_USERNAME`.
- **Host:** these endpoints live on the DM host under `/api/core/…`. The
exception is edX user roles (list / promote-demote / bulk sync), which flip
to the edX LMS/CMS host - see the **Users > Roles (edX)** entries below. The
`org` field on those calls is the edX course-organization short name, not
the ibl.ai `org key` - see the reference doc linked in `## Reference
material`.
- Not connected yet? Run **`/iblai-api-login`** first to populate `IBLAI_ORG`,
`IBLAI_USERNAME`, and `IBLAI_API_KEY`.
## Reads
### Users
- **GET** `…/core/platform/users/?platform_key={org}&platform_org={org}&query={q}&page={n}&page_size=10&return_policies=true` — user list + policies.
#### Roles (edX)
- **GET** `https://studio.learn.iblai.app/api/ibl/users/manage/roles/?username={username}` - list a user's edX roles (global + course + org). Identify the user with `username`, `email`, or `user_id`. Full role catalog (what each role key means, which need `course`/`org`) and endpoint detail in **[`references/edx-roles-reference.md`](references/edx-roles-reference.md)**.
### Groups
`…/core/rbac/groups/`
- **GET** `…/groups/?platform_key={org}&include_users=true[&name=&email=&owner=&username=&page=&page_size=]` — list.
- **GET** `…/groups/{id}/` — detail.
### Roles
`…/core/rbac/roles/` (all calls include `include_global_roles=true`)
- **GET** `…/roles/?include_global_roles=true&platform_key={org}[&name=&page=&page_size=]` — list.
- **GET** `…/roles/{id}/?include_global_roles=true&platform_key={org}` — detail.
### Policies
`…/core/rbac/policies/`
- **GET** `…/policies/?platform_key={org}&include_groups=true&include_users=true[&role_id=&group=&name=&username=&email=&page=&page_size=]` — list.
- **GET** `…/policies/{id}/?platform_key={org}` — detail.
### Teams
`…/core/user-groups/` plus team access (`…/core/rbac/teams/access/`)
- **GET** `…/user-groups/?platform_key={org}[&include_users=&name=&with_permissions=&page=&page_size=]` — list.
- **GET** `…/user-groups/{id}/?platform_key={org}` — detail.
- **GET** `…/core/rbac/teams/access/?platform_key={org}&usergroup_id={id}` — list a team's access policies.
## Writes
### Users
#### Roles (edX)
- **POST** `https://studio.learn.iblai.app/api/ibl/users/manage/roles/` - promote/demote, i.e. assign or unassign one role:
```json
{
"username": "string (required)",
"role": "e.g. org-instructor (required - see role catalog)",
"course": "course id - required for course roles",
"org": "edX course-org short name - required for org roles",
"active": "boolean (optional, default true - true assigns, false removes)"
}
```
General roles (`staff`, `support-staff`, `course-creator`) take neither
`course` nor `org`. `course-creator` is CMS-only (the LMS host rejects it
with `400`). Full role catalog - what each key means and its scope
requirement - is in **[`references/edx-roles-reference.md`](references/edx-roles-reference.md)**.
- **POST** `https://studio.learn.iblai.app/api/ibl/users/manage/roles/sync/` - bulk-replace a batch of role assignments for one user in a single atomic request (all entries validated first; all succeed or all roll back). Body and response shape, plus inactive-user and idempotency behavior, in the reference doc above.
- **POST** `…/core/users/platforms/` — activate/deactivate:
```json
{
"user_id": "number (required)",
"platform_key": "string (required)",
"active": "boolean (required)"
}
```
- **PUT** `…/core/platform/users/policies/` — set policies (array):
```json
[
{
"user_id": "number (required)",
"platform_key": "string (required)",
"policies_to_set": "string[] (required, may be [])"
}
]
```
### Groups
`…/core/rbac/groups/`
- **POST** `…/groups/` — create:
```json
{
"name": "string (required)",
"platform_key": "string (required)",
"description": "string",
"users": "number[]"
}
```
- **PUT** `…/groups/{id}/` — update (same shape).
- **DELETE** `…/groups/{id}/?platform_key={org}` — delete. Destructive — confirm with the user first.
### Roles
`…/core/rbac/roles/` (all calls include `include_global_roles=true`)
- **POST** `…/roles/?include_global_roles=true` — create:
```json
{
"name": "string (required)",
"platform_key": "string (required)",
"actions": "string[] (RBAC action strings, e.g. Ibl.Mentor/Mentors/read)",
"data_actions": "string[]"
}
```
The permission list is **`actions`** (+ optional **`data_actions`**), not
`permissions`. See **`/iblai-api-rbac`** for the full role/policy model
(action namespaces, resource paths).
- **PUT** / **PATCH** `…/roles/{id}/?include_global_roles=true` — update (same shape).
- **DELETE** `…/roles/{id}/?include_global_roles=true&platform_key={org}` — delete. Destructive — confirm with the user first.
### Policies
`…/core/rbac/policies/`
- **POST** `…/policies/` — create:
```json
{
"name": "string (required)",
"platform_key": "string (required)",
"role": "number role id (required)",
"resources": "string[]",
"users": "number[]",
"groups": "number[]"
}
```
- **PUT** / **PATCH** `…/policies/{id}/` — update (same shape).
- **DELETE** `…/policies/{id}/?platform_key={org}` — delete. Destructive — confirm with the user first.
### Teams
`…/core/user-groups/` plus team access (`…/core/rbac/teams/access/`)
- **POST** `…/user-groups/` — create:
```json
{
"name": "string (required)",
"platform_key": "string (required)",
"description": "string",
"users": "number[]"
}
```
- **PUT** `…/user-groups/{id}/` — update (same shape).
- **DELETE** `…/user-groups/{id}/` — delete. Destructive — confirm with the user first.
- **POST** `…/core/rbac/teams/access/` — set team access:
```json
{
"platform_key": "string (required)",
"usergroup_id": "number (required)",
"groups": "[{group_id, role}]",
"users": "[{user_id, role}]"
}
```
### Alerts
`…/core/watched-groups/`
- **GET** / **POST** `…/watched-groups/` — list / create watched group.
- **GET** / **PATCH** / **DELETE** `…/watched-groups/{id}/` — watched group detail / update / delete. DELETE is destructive — confirm with the user first.
- **GET** / **POST** `…/watched-groups/{watchedGroupPk}/watched-users/` — list / add watched users.
- **DELETE** `…/watched-users/{id}/` — remove watched user. Destructive — confirm with the user first.
- **GET** / **POST** `…/watched-groups/{watchedGroupPk}/watchers/` — list / add watchers.
- **PATCH** / **DELETE** `…/watchers/{id}/` — update / remove watcher (notification-event flags in body). DELETE is destructive — confirm with the user first.
## Example
List the first page of organization users with their policies:
```bash
curl -s \
"https://api.iblai.app/dm/api/core/platform/users/?platform_key=$IBLAI_ORG&platform_org=$IBLAI_ORG&page=1&page_size=10&return_policies=true" \
-H "Authorization: Api-Token $IBLAI_API_KEY"
```
## Notes
- Most endpoints require `platform_key={org}` as a query param even on POST/PUT
bodies that also carry it — send both.
- The edX user-roles calls (list, promote/demote, bulk sync) are the only
ones on the edX LMS/CMS host and take **no** `platform_key`; every other
endpoint here is on the DM host under `/api/core/…`. Prefer the CMS host
(`studio.learn.iblai.app`) for edX roles - it accepts every role key,
including `course-creator`, which the LMS host rejects.
- edX roles (this section) and DM `rbac/roles` (the **Roles** subsection
below) are two unrelated systems that happen to share the word "role" - an
edX role key like `org-instructor` is not a DM RBAC role id, and vice versa.
- Policies bind a `role` (RBAC role id) to `resources`, `users`, and `groups` —
create the Role first, then reference its id when creating the Policy.
- DELETE on any sub-section is destructive — confirm with the user before
removing groups, roles, policies, teams, watched groups/users, or watchers.
## Reference material
- **[`references/edx-roles-reference.md`](references/edx-roles-reference.md)** - full edX role catalog (every global/course/org role key and what it grants), the list/assign/bulk-sync endpoint bodies and responses, and gotchas (inactive-user grant skipping, idempotency, `course-creator`'s CMS-only restriction, Open edX release gates on `course-limited-staff`).