Skip to content

API

Use these routes to work with skills, jobs and workspaces. The API may change.

Calling it

The API is a separate service from this static app host. Open Claude Code in your workspace: the installation command names its base URL in SLANCHA_API_URL, and the existing-CLI command names the same URL after slancha auth --api. Use that exact base URL; /api paths are appended to it, not to https://app.slancha.ai.

Every route below is under /api. Send Authorization: Bearer <token>. The console sends the access token of the signed-in person. A personal token (slancha_pat_...) is for the CLI: it lists skills, downloads published versions and reports usage. The routes that manage the library, jobs, keys and tokens refuse it.

An agent token, from slancha auth --manage, is a personal token that can do more. It has its owner's role, but never above proposer, and expires 30 days after it was approved; an expired one gets 401 this token expired; run slancha auth again. It can call GET /api/me, GET /api/agent-jobs, GET /api/tracing/status, every read under The library and the criteria check, the upload, and the routes under Scans, drafts and jobs. It starts drafts and outcome jobs only while an admin allows agent jobs (PUT /api/agent-jobs); otherwise those answer 403. Every other route refuses it with 403, including approve, reject, rollback, setting criteria, keys, tokens, members and CLI approval.

Set X-Ingot-Org to a workspace ID returned by GET /api/me. It selects a workspace you already belong to; it does not grant membership.

Most refusals come back as JSON with a detail string in plain words. A request body or query value that fails validation (for example a missing value on PUT /api/keys/openai, or days outside 1 to 90) answers 422 with detail as a list of structured entries instead. POST /api/cli/token follows RFC 8628 and answers error and error_description. A route the hosted API does not serve answers 404 Not Found. Core library and token routes work at signup. Mining routes require a separate premium entitlement; tracing is optional.

Roles are viewer, proposer, approver, admin. Each row names the lowest role that may call it. A personal token never acts as a person on the routes marked "person".

Identity and workspaces

RouteRoleDoes
GET /api/meanyYour user, email, role, the current workspace and its status, and all your workspaces. With a token, also its capabilities and expires_at (epoch seconds, or null).
GET /api/agent-jobsanyWhether agent tokens may start drafts and outcome jobs: enabled, enabled_by, enabled_at, and max_run_usd, the workspace's cost cap for each run.
PUT /api/agent-jobs {enabled, acknowledge?}admin{"enabled": true, "acknowledge": "traces-to-model-provider-v1"} lets agent tokens start them, which says the admin knows a draft sends scrubbed session excerpts to the model provider. {"enabled": false} stops them. Answers as the GET does.
POST /api/orgs {name}personCreates a workspace with you as admin. Core sharing is available immediately.
PUT /api/orgs/{id} {name}adminRenames the workspace without changing its slug.
PUT /api/orgs/{id}/members {email, role}adminChanges an existing member or invitation role.
DELETE /api/orgs/{id}/members {email}adminRemoves a member and their workspace tokens, or revokes a pending invitation. Keeps a signed-in admin.
GET /api/orgs/{id}/membersmemberLists members.
POST /api/orgs/{id}/invites {email, role}admin of that workspaceAdds an existing account or creates a pending invitation claimed at first sign-in. Sends no email.
POST /api/orgs/{id}/members {email, role}admin of that workspaceAdds a member by email, or changes their role. The person claims it at first sign-in.

The library

RouteRoleDoes
GET /api/skillsviewer, or personal tokenLists skills: name, description, served version, pending change, scan result, use in the last seven days.
GET /api/skills/{skill}/versionsviewerThe served version, the pending change, and every publication.
GET /api/skills/{skill}/versions/{revision}viewerOne version's files as text.
GET /api/skills/{skill}/download?revision=viewer, or personal tokenA published version as a zip. The response carries X-Slancha-Revision and X-Slancha-Sha256.
GET /api/pending, GET /api/pending/{skill}viewerThe review queue, and one card with its diff, scan and evidence. The card's criteria is how the change does against the acceptance criteria; each failure makes gate.promotable false and is listed in gate.blocked as acceptance criteria: <rule>: <reason>.
GET /api/skills/{skill}/criteriaviewerThe acceptance criteria: rules, labels (each rule as text), updated_by, updated_at, and how the served and the pending version do (served, pending): ok, each rule's label, ok and reason, and failures.
PUT /api/skills/{skill}/criteria {rules}adminReplaces the rules; an empty list removes them. A rule is {type: "includes" | "excludes", path, text} (path * for every file, excludes only), {type: "file", path}, {type: "max_kb", value} or {type: "frontmatter", key}. Up to 50 rules. A rule that cannot be checked answers 400, for example rule 3: text must be 1 to 500 characters. Answers as the GET does.
POST /api/skills/{skill}/criteria/check {revision} or {files} or {archive}proposerChecks a stored version, or a package shaped like an upload, against the rules. Stores nothing.
GET /api/historyviewerPublications and the skill audit trail.
POST /api/skills/uploadproposerStores a proposal and starts its scan. Send {name?, files: [{path, content}]} or {name?, archive} with a base64 zip. Answers 201 with the proposal id, the scan job and how it does against the acceptance criteria.
POST /api/promote/{skill} {proposal_id}approverApproves. Refused if the proposal was replaced, is stale, or its scan has not cleared, and with 409 acceptance criteria not met: … if it fails a rule.
POST /api/reject/{skill} {proposal_id, reason?}approverRejects.
POST /api/rollback/{skill}/{revision}approverServes an earlier version, or absent to stop serving. The acceptance criteria do not block it; result says when the version fails them.

A revision is a 64-character hex digest.

Scans, drafts and jobs

RouteRoleDoes
POST /api/skills/{skill}/scan {revision?}proposerStarts a scan. Answers 202 with the job.
GET /api/skills/{skill}/scan?revision=viewerThe stored scan: cleared or not, the scanner's recommendation, findings.
POST /api/draft/{skill}adminStarts a draft job. Send {"acknowledge": "traces-to-model-provider-v1"}, which says the admin knows scrubbed session excerpts go to the model provider. A new skill also needs project and description. Answers 202 with the job.
GET /api/wiki/{skill}viewerThe skill's wiki pages. 404 until its first draft.
GET /api/jobs, GET /api/jobs/{id}viewerJobs, newest first, the latest 50; filter with ?skill=. A job is queued, running, succeeded, failed or cancelled.
POST /api/jobs/{id}/cancelproposerCancels a running job.

Keys and tokens

RouteRoleDoes
GET /api/keysany memberWhich providers have a key. Never a key.
PUT /api/keys/openai {value}adminStores the OpenAI key. Other providers are refused. The key is stored encrypted. When the deployment names its job model, OpenAI is asked whether the key can read that model's metadata. A 401, 403 or 404 is refused with 400 and the key is not saved. A 200 confirms only that read, not permission to run a draft. If no model is named, OpenAI cannot be reached, or it answers with any other status, the key is saved and the response says it was not checked.
DELETE /api/keys/{provider}adminDeletes a key.
GET /api/tokens, POST /api/tokens {name}, DELETE /api/tokens/{id}personYour own personal tokens. The token value comes back once, from the POST. Each listed token has its capabilities (manage for an agent token) and expires_at (epoch seconds, or null).
GET /api/skills/{skill}/usage?days=personUse by version. days is 1 to 90, default 30.
POST /api/usage/skills {events}personal tokenReports skill use. The CLI sends it.

Tracing

RouteRoleDoes
GET /api/tracing/status?since=viewerConnection configuration and health, whether traces are arriving, counts by skill, the projects sessions ran in, and outcome counts. An unconnected workspace is a normal response. Checks are cached for up to one minute. since is epoch seconds; the default is seven days.
PUT /api/tracing/connection {project_id, jobs: {public_key, secret_key}, ingest: {public_key, secret_key}}adminConnects the workspace's Langfuse project. Both distinct key pairs must belong to that project. Stores encrypted keys; does not enable mining. An existing connection requires operator replacement.
POST /api/tracing/requestadminRequests Slancha-managed setup. The durable, idempotent request appears in the operator Admin tab. It remains pending until an operator connects the project; it does not start capture or enable mining.
GET /api/tracing/credentialsadminThe workspace's tracing host and keys. Each read is recorded.

CLI sign-in

These follow the device grant in RFC 8628.

RouteWhoDoes
POST /api/cli/device {client?, tracing?, manage?}nobody yetAnswers a device_code, a user_code like ABCD-EFGH, verification_uri, verification_uri_complete, expires_in of 600 seconds and an interval of 5. tracing and manage are booleans, false by default. tracing explicitly requests tracing credentials and requires admin approval. manage asks for an agent token and requires a proposer or above.
GET /api/cli/device/{user_code}member, signed inRead-only preview: the CLI's self-reported client, age_seconds, tracing_requested and manage_requested. Tracing requests require an admin. The client name is not verified identity.
POST /api/cli/approve {user_code}member, signed inApproves personal skill access for the current workspace. A request for tracing keys requires an admin; a request to manage requires a proposer or above.
POST /api/cli/token {device_code}the CLIAnswers 400 authorization_pending until approval, or expired_token once the code has expired or been used. After approval it answers once with a personal token (an agent token for manage), the workspace id, its capabilities and expires_at, and tracing keys only when requested and approved by an admin.

Operators

GET /api/admin/orgs?status= and PUT /api/admin/orgs/{id}/langfuse are for Slancha operators, who manage optional tracing separately from workspace access. PUT /api/admin/orgs/{id}/mining with {enabled} controls premium mining. Everyone else gets a 404.