Headless API skills — the `iblai-api-*` contract
Mirrored from
iblai/vibe·docs/api-skills.md. This page is generated — edit it in the repository, not here.
The iblai-api-* skills operate the ibl.ai platform without a user
interface: each maps one capability to its exact api.iblai.app REST
endpoints (method, URL, body, errors) so an agent, a script, a CI job, or a
server route calls the platform correctly the first time. They came from the
former iblai/api repository and keep its contract, reproduced here. The
visual-component skills (iblai-vibe-*, kind ui) are described in
skill-kinds.md.
Using an API skill
Connect once:
/iblai-api-login— signs the user in (ibl.ai/join if new, login.iblai.app/me otherwise), captures the org key and username, mints a Platform API Token, and writes them to.envandiblai.env. An org secret works directly as the token for headless/CI use.Every call: base URL
https://api.iblai.app(orhttps://api.$DOMAINwhen self-hosted), headerAuthorization: Api-Token $IBLAI_API_KEY. Path variables:{org}=$IBLAI_ORG(a.k.a.platform_key),{username}=$IBLAI_USERNAME,{mentor}= an agent'sunique_id.Load the credentials from whichever file the project has:
set -a; [ -f .env ] && . ./.env; set +a val() { grep -m1 "^$1=" iblai.env 2>/dev/null | cut -d= -f2-; } : "${IBLAI_ORG:=$(val PLATFORM)}"; : "${IBLAI_API_KEY:=$(val TOKEN)}"; : "${IBLAI_USERNAME:=$(val IBLAI_USERNAME)}" DOMAIN="${DOMAIN:-$(val DOMAIN)}"; DOMAIN="${DOMAIN:-iblai.app}"; API="https://api.$DOMAIN"IBLAI_ORG=PLATFORM=NEXT_PUBLIC_MAIN_TENANT_KEY;IBLAI_API_KEY=TOKEN. Never commit either file; never print the token.Destructive or outward-facing calls (delete, send, invite, checkout) are marked "confirm with the user first" — do.
Inside a Next.js app, the same endpoints are called from a server route with
lib/iblai/platform.ts— see/iblai-vibe-api. In the browser, use the SDK hook instead (it carries the user's session).
Runtime chat: the hosted MCP server
Skills cover everything reachable over REST. The one runtime capability
that is not a REST admin call — holding a live conversation with a deployed
agent (streamed responses, tool use, RAG) — is a hosted Model Context Protocol
server, iblai-agent-chat (mcp/iblai-agent-chat/README.md). Wire it with
/iblai-api-agent-chat; talk over raw REST/SSE with /iblai-api-agent-session
instead when you want transport control. Rule: if a skill covers it, there
is no server for it.
This is a different server from @iblai/mcp in .mcp.json, which gives your
coding assistant the SDK's component and hook documentation.
Authoring contract (when you add or change an iblai-api-* skill)
Structure and sources of truth
Where a skill lives:
skills/<category>/<name>/SKILL.md. The nine categories —start,agents,users,organizations,billing,analytics,content,ship,security— and every skill's category are recorded inscripts/skill-categories.json; add a new skill there too. Installs flatten the tree, so a skill is always.claude/skills/<name>/at runtime — never write a category segment into a.claude/skills/…path.Each skill is a
SKILL.mdwith YAML frontmatter (name,description) following the format ofskills/agents/iblai-api-agent-setting/SKILL.mdandskills/start/iblai-api-login/SKILL.md. A skill MAY additionally bundle areferences/directory and anassets/directory for sample files, each linked fromSKILL.mdvia a## Reference materialsection.references/holds anything that would bloat the scannable primary: exhaustive lookup tables (field schemas, action catalogs) and the developer docs' fuller explanatory material — concepts, architecture/data-flow, configuration and integration guides, and troubleshooting (this is where non-endpoint doc content that doesn't belong in the endpoint-focusedSKILL.mdis preserved, including UI/integration walkthroughs).SKILL.mditself stays the scannable, endpoint-focused primary and still obeys the "APIs not UIs" rule;references/is doc-sourced supplementary material. Seeskills/organizations/iblai-api-external-service-proxy/,skills/organizations/iblai-api-crm/, andskills/agents/iblai-api-agent-memory/for the pattern.Canonical section structure (every endpoint-documenting skill MUST follow this):
## Auth & conventions— base URL, header, path vars, prefix, "run/iblai-api-loginfirst" line, and the destructive-confirm note.- (optional) one short explanatory section (e.g.
## Concepts,## Pagination) when the API needs framing before the endpoints. ## Reads— every read endpoint (GET/HEAD).## Writes— every write endpoint (POST/PUT/PATCH/DELETE); mark each destructive/outward-facing call "Confirm with the user first."## Example— one realisticcurl.## Notes— gotchas.
- Multi-resource skills (catalog, crm, rbac, billing, …) keep their resource grouping as
###sub-headings inside## Readsand## Writes(a resource with both appears under each). Do not group endpoints by resource at the top level — Reads/Writes is always the top-level split. - A read-only skill may omit
## Writes; a write-only skill may omit## Reads. - Exceptions: non-REST skills do not use Reads/Writes —
iblai-api-loginandiblai-api-agent-chat(setup flows), andiblai-api-infrastructureandiblai-api-ecosystem(deployment / open-source-ecosystem guides sourced from the developer docs, content held inreferences/). These are guides, not endpoint references.
Auth model (every skill): base URL
https://api.iblai.app, headerAuthorization: Api-Token $IBLAI_API_KEY. Path vars{org}=$IBLAI_ORG(a.k.a.platform_key),{username}=$IBLAI_USERNAME,{mentor}= the agent's unique id.Gateway prefixes —
/dmand/edx.api.iblai.appis a gateway that sits in front of the backend services and strips a prefix before routing:https://api.iblai.app/dm/...→ the Data Manager service (theiblai/iblai-dm-pro(private backend repo) repo).https://api.iblai.app/edx/...→ the Open edX service (a different system).
The prefix is added at the gateway, so it does not appear in any backend
urls.py— the source repos register bare/api/...routes. A skill must prepend the right prefix (e.g. a DM route/api/catalog/courses/is documented and called ashttps://api.iblai.app/dm/api/catalog/courses/). When in doubt, an endpoint is a/dmendpoint.Source of truth = the repo URLconf, not the docs. Skills for DM features are derived from
iblai-dm-pro. The appUSAGE.mdfiles are a starting point but contain errors, gaps, and (critically) endpoints that only apply to edX — those do not belong here. Rule: only document an endpoint if it is registered in that repo'surls.py(i.e. reachable atapi.iblai.app/dm/...). If a path is not in this repo's URL configuration, drop it — it would not resolve via/dm. Always verify each endpoint's method, path, and request fields against the actualurls.py/ views / serializers before shipping a skill.Connecting an organization:
/iblai-api-loginopenshttps://login.iblai.app/me, lets the user pick one of their organizations, and writesIBLAI_ORG,IBLAI_USERNAME, andIBLAI_API_KEYto.env. Always ask the user which org to target — accounts can belong to many (40+ is normal).- Logged out:
/meredirects to/login. Detect this (URL is/login, no "My Account" content), hand the user thehttps://login.iblai.app/meURL, and wait for them to sign in — never enter their credentials. - After login the platform redirects somewhere else (the destination varies and may change), NOT back to
/me. Don't depend on where it lands — always re-navigate explicitly tohttps://login.iblai.app/mebefore reading params. /meis server-rendered — there is no JSON API; read org keys + username from the rendered page content. Each org block is the display name followed by its key (e.g.Enterprise → enterprise,ibl.ai → iblai, or a UUID).- There is no working logout route (
/logout,/api/auth/logoutboth 4xx); the session is an httpOnly cookie. To force a logged-out state for testing, clear the browser's cookies forlogin.iblai.app.
- Logged out:
Mark every DELETE / destructive / outward-facing call (delete, send, invite) "confirm with the user first."
Terminology (settled — use consistently)
The wire and the prose use different words for the same things. Prose in this
repo uses organization / org key, agent, and user. The words tenant,
mentor, and learner appear only as verbatim wire names, in backticks.
- Platform — the ibl.ai system as a whole (
api.iblai.app,login.iblai.app). One platform serves every customer. Never use "platform" to mean a single customer's workspace. (It is fine in product terms like "Platform API Token" and in prose like "the platform API".) - Organization (org) — one customer's isolated workspace (its own users, agents, branding, data). This is the primary noun in all prose and docs. It matches what customers see on
login.iblai.app/me("Organizations") and the API path/orgs/{org}/. - org key — the organization's identifier, e.g.
enterprise. On the API wire it also appears asorg,platform_key, andplatform_org— keep those verbatim in endpoint references; they all mean the org key. - Agent — a configured AI assistant. On the wire it is
mentor(mentor_unique_id,/mentors/{mentor}/, theX-Mentor-Unique-Idheader) — keep those verbatim. - User — a person with an account in the org. On the wire, LMS/catalog routes sometimes say
learner— keep that verbatim where the API does. tenant— a wire name only, never prose. Not even as an adjective: write "multi-organization", "organization isolation", "organization key" — not "multi-tenant", "tenant isolation", "tenant key". Write`tenant`in backticks only where the API or the SDK really uses it: thetenantquery param on some search endpoints,localStoragekeystenant/tenants/current_tenant/visiting_tenant, and the SDK'sTenantProvider/useTenantSwitch/NEXT_PUBLIC_MAIN_TENANT_KEY/IBL_TENANT. Note the MCP scope enum isuser|mentor|platform, not…|tenant. The@iblaiSDK / vibe / os keeptenantin env vars; this repo's own env vars deliberately useorginstead.
Env vars follow the noun: active workspace is IBLAI_ORG + IBLAI_API_KEY; saved per-workspace keys are IBLAI_ORG_<NAME>_KEY.
Naming
Scope is encoded by prefix: iblai-api-agent-* acts on one agent;
iblai-api-profile* on the signed-in user; org-wide skills are bare
(iblai-api-management, -rbac, -crm, -token, -integration,
-notification, -invite; iblai-api-org is the org-settings skill);
cross-cutting skills are bare too (-search, -analytics, -course-create,
-login). Every iblai-api-* skill carries metadata.kind: api (or guide
for the two non-REST guides, -ecosystem and -infrastructure).
Verification
Run bash scripts/validate-skills.sh, node scripts/check-skill-kinds.mjs,
node scripts/check-links.mjs, node scripts/build-adapters.mjs, and
node scripts/check-skill-tables.mjs before opening a PR; confirm each
endpoint against the live OpenAPI schema
(https://api.iblai.app/dm/api/docs/schema/) and the backend URLconf.
Building a new MCP server
# Install dependencies
cd mcp/iblai-<service>
uv sync
# Run the server
uv run iblai-<service>
# Run tests
uv run pytest
Each server contains:
- server.py: tool definitions via
@server.tool()decorators - auth.py:
AuthManagersupporting api_key, bearer, basic, custom_header, oauth2_client_credentials via env vars - client.py:
APIClientfor async httpx requests
Conventions: server names iblai-<service>, package names iblai_<service>; stdio transport locally, streamable-http for hosted. The hosted servers expect Authorization: Api-Token <key>; the org is derived from the token.
Tutorials
tutorials/ holds end-to-end walkthroughs that combine several iblai-api-*
skills into a working result (e.g. tutorials/voice-agent: an agent on your
own server that places outbound phone calls).