Last updated

/iblai-vibe-api

Mirrored from iblai/vibe Β· skills/start/iblai-vibe-api/SKILL.md. This page is generated β€” edit it in the repository, not here.

First time here? If iblai.env has no ARCHITECTURE=, run /iblai-vibe-start first (four questions; two minutes) β€” it decides single-org / multi-org / headless and who signs in, and every skill reads the answer.

Every /iblai-vibe-* skill mounts an SDK component. When none exists for what the user wants, do not build a workaround in the browser β€” call the platform's REST API from a Next.js route handler with the org's Platform API Token. Everything the platform can do is reachable that way; the iblai-api-* skills (kind api, same repo) document each endpoint (method, URL, body, errors).

Common setup (brand, conventions, env files, verification): see docs/skill-setup.md. Terms: docs/glossary.md.

The one rule

Where the code runsCredentialHeaderUse for
Browser (client components)the signed-in user's session token, attached by the SDK automaticallyAuthorization: Token <dm_token>everything an SDK hook or component offers; acts as the user, with the user's permissions
Server (route handlers, server actions)IBLAI_API_KEY (= TOKEN in iblai.env) via config.apiKey()Authorization: Api-Token <key>anything without a hook, and anything that needs the org's authority (admin writes, cross-user reads, creating agents, sending notifications)
Server, OpenAI-compatible /v1 onlythe same keyAuthorization: Bearer <key>chat completions / model listing on https://asgi.data.<domain>/api/ai-mentor/orgs/<org>/v1

Never prefix the key with NEXT_PUBLIC_, never read it outside server files, never send it to the browser. config.apiKey() returns "" in the browser by design.

Step 1: Install the helper

Render assets/platform.ts.j2 β†’ lib/iblai/platform.ts. It exports:

  • platformFetch(path, init?) β€” server-only fetch against https://api.<DOMAIN> with the Api-Token header, JSON in/out, and a typed PlatformError carrying the platform's status and body.
  • verifyCaller(req) β€” reads the Authorization: Token <dm_token> the browser forwards, calls GET /dm/api/core/token/verify/, and returns the caller's username; null when the token is missing or rejected.
  • requireAdmin(req) β€” verifyCaller plus an org-membership check that the caller is an admin of NEXT_PUBLIC_MAIN_TENANT_KEY (via GET /dm/api/core/platform/users/?platform_key=&query=<username>), or a 401/403 NextResponse.

The browser side sends its token like this (already how vibe-starter's lib/iblai/metadata.ts does it):

const token = localStorage.getItem("dm_token") ?? "";
await fetch("/api/admin/whatever", {
  method: "POST",
  headers: { Authorization: `Token ${token}`, "Content-Type": "application/json" },
  body: JSON.stringify(payload),
});

Step 2: Write the route

Render assets/route-example.ts.j2 β†’ app/api/admin/example/route.ts as the pattern to copy: verify the caller, validate the body, call the platform, return its answer, map errors.

Status mapping to keep: platform 401 β†’ your 401; 403 β†’ 403 (not an admin / not allowed); 404 β†’ 404; 429 β†’ 429 (spend cap hit β€” pass the body through, it names the interval); anything else β†’ 502 with the platform's message.

Three worked examples

A Β· An admin writes another user's metadata

Only org admins may target &username=<other>; the SDK hook has no such parameter, so it is a server call.

// inside a route handler, after requireAdmin(req)
await platformFetch(
  `/dm/api/core/users/platform-metadata/?platform_key=${org}&username=${encodeURIComponent(target)}`,
  { method: "PATCH", body: { metadata: { role_label: "mentor" }, delete_keys: [] } },
);

Reference: profile-metadata.

B Β· Create an agent

const agent = await platformFetch<{ unique_id: string }>(
  `/dm/api/ai-mentor/orgs/${org}/users/${caller.username}/mentor-with-settings/`,
  {
    method: "POST",
    body: {
      template_name: "ai-mentor",
      new_mentor_name: name,
      display_name: name,
      description,
      system_prompt: systemPrompt,
    },
  },
);
// agent.unique_id is the UUID every other agent skill needs

Reference: agent-create; the full UI pattern is /iblai-vibe-agent-create.

C Β· Send a notification to a user

await platformFetch(`/dm/api/notifications/orgs/${org}/send/`, {
  method: "POST",
  body: { username: target, title: "Welcome", body: "Your account is ready." },
});

Confirm the exact path and body in notification before shipping β€” notification sending is outward-facing; confirm the recipient list with the user first.

Which iblai-api-* skill documents what

They install with the rest of this repo's skills (npx skills add iblai/vibe --all); raw links resolve without installing. The five families most apps read or write are marked β˜….

NeedSkill
β˜… Per-user custom data (preferences, flags, onboarding, app state)profile-metadata
β˜… The user's own profile (name, bio, image, education, rΓ©sumΓ©)profile
β˜… Agent identity, visibility, capability flags; fork; deleteagent-setting
β˜… Memory: global, per-agent, agent knowledge, togglesagent-memory
β˜… Analytics: usage, users, topics, transcripts, costs, per-user, audit, reportsanalytics
Org settings (default agent, help URL, toggles, your keys)org
Users, groups, roles, policies, teams, alertsmanagement, rbac
Invitations (single, CSV)invite
Directory sync (SCIM 2.0)scim
Create an agent; chat over REST/SSE/WebSocket; sessionsagent-create, agent-session, agent-chat
Agent tabs: prompts, LLM, datasets, tools, access, embed, MCP, safety, privacy, evals, audit, history, sandbox, skills, support, disclaimersiblai-api-agent-<tab> β€” see /iblai-vibe-agent for the map
LLM inference with the platform key (OpenAI-compatible)inference
Search agents and content; recommendationssearch
Notifications: counts, inbox, mark read, sendnotification
Credits, paywalls, checkout, subscriptions, revenuebilling
Spend caps (org / agent / user)spend-caps
Per-user feature config, app onboarding flags, trialsfeature
API tokens; LLM / data-source credentialstoken, integration
Courses, programs, catalog, milestones, credentials, media, applicationscatalog, milestone, credential, apply
CRM (people, deals, pipelines)crm
Third-party AI services through the platform (ElevenLabs, HeyGen)external-service-proxy
Self-hosting the backendinfrastructure

The schema is the contract

Before constructing any URL not copied from a skill, confirm it exists in the live OpenAPI schema:

DOMAIN=$(grep -m1 '^DOMAIN=' iblai.env 2>/dev/null | cut -d= -f2-); DOMAIN=${DOMAIN:-iblai.app}
curl -sS -o /tmp/iblai_schema.yaml "https://api.$DOMAIN/dm/api/docs/schema/"
grep -nE "^  /api/core/users/platform-metadata" /tmp/iblai_schema.yaml

Browsable at https://api.iblai.app/dm/api/docs/. Gateway rule: DM routes are called with the /dm prefix (/api/core/… β†’ /dm/api/core/…); edX routes with /lms.

Verify

  1. pnpm typecheck and pnpm test (the helper ships with a unit test in assets/platform.test.ts.j2 β†’ __tests__/platform.test.ts).
  2. Exercise the route with a signed-in browser (the token header) β€” expect 401 without it, 403 as a non-admin, 200 as an admin.
  3. Nothing prints the key: grep -rn "IBLAI_API_KEY" app components lib | grep -v "config.apiKey\|process.env.IBLAI_API_KEY" returns nothing.
  • /iblai-vibe-user-metadata, /iblai-vibe-org-metadata, /iblai-vibe-agent-create β€” the three common cases, done end to end
  • /iblai-vibe-admin β€” gating admin-only routes and pages
  • /iblai-vibe-ops-deploy β€” the server env (IBLAI_API_KEY) on the hosting platform

Copyright Β© ibl.ai | support@iblai.zendesk.com