The project's publishing flow — review_required, direct_publish or ai_assisted. Tells you what a publish into this project will do before you attempt one.
Appearance
Appearance
GET /skillsThe skills a key can reach — the discovery counterpart of GET /prompts. On-prem only.
Two shapes, depending on the scope you ask for. Pass exactly one of project_id or organization_id.
| Parameter | Notes |
|---|---|
project_id | the effective skill set for one project |
organization_id | the promotion ladder, plus every project you can reach |
Both key transports work here, as on the read endpoints.
Listing vs. resolving
GET /skills?project_id=… and GET /skills/resolve return the same resolved set for a project — listing is resolve at format=index, wrapped with the project's name and flow mode. Use resolve when you want bodies; use this when you want an inventory, or when you want the organisation view.
curl -s "$IM_URL/skills?project_id=8112d9c4-8334-43dd-a3c0-436b5cf1f475" \
-H "X-API-Key: $IM_KEY"{
"project_id": "8112d9c4-8334-43dd-a3c0-436b5cf1f475",
"project_name": "sample",
"flow_mode": "ai_assisted",
"total": 2,
"skills": [
{ "name": "sonar-clean-code",
"version": { "sha": "aacea0c4cd13", "version_label": "v1.0" },
"resolution": { "tier": "organization", "shadowed": [], "pinned": false } },
{ "name": "test",
"version": { "sha": "a28b804cda57", "version_label": "v1.0" },
"resolution": { "tier": "project", "shadowed": [], "pinned": false } }
]
}Skills are tiered — project, organisation and global — and this returns the effective set after resolution, including which tier won and what it shadowed. That is the same resolution the runtime performs, so what you list is what a consumer would actually get. See Resolution & pins.
flow_modestringThe project's publishing flow — review_required, direct_publish or ai_assisted. Tells you what a publish into this project will do before you attempt one.
A skill is promoted one tier at a time: project → organisation → global. Organisation scope reports that ladder rather than flattening it, because "available to every project in this org" and "lives in one project" are different facts about a skill, and a picker has to tell them apart.
curl -s "$IM_URL/skills?organization_id=d7fb6107-1188-4f7c-97e2-978403f3e3be" \
-H "X-API-Key: $IM_KEY"{
"organization_id": "d7fb6107-1188-4f7c-97e2-978403f3e3be",
"organization_skills": [
{
"name": "helper",
"version": { "sha": "aacea0c4cd13" },
"resolution": { "tier": "organization" },
"promoted_from": { "scope": "project", "scope_id": "831172bf-bf48-4720-b1dd-df9b891cca48" }
}
],
"installed_skills": [
{
"name": "helper",
"version": { "sha": "f10c3b7e21a4" },
"resolution": { "tier": "global" },
"promoted_from": { "scope": "organization", "scope_id": "d7fb6107-1188-4f7c-97e2-978403f3e3be" }
}
],
"projects": [
{
"project_id": "8112d9c4-8334-43dd-a3c0-436b5cf1f475",
"project_name": "sample",
"flow_mode": "ai_assisted",
"skills": [ "…" ]
}
]
}organization_skillsarraySkills promoted to this organisation, and therefore available to every project in it. Each carries resolution.tier: "organization".
installed_skillsarrayGlobal-tier skills installed at organisation level, with resolution.tier: "global".
Listed separately because they cannot be found by organisation id at all — a global skill is stored with no owning organisation, and is reachable only through its install record.
promoted_fromobjectThe origin scope of a promoted skill: { "scope", "scope_id" }. Answers "where did this come from?" — a project id for an organisation skill, an organisation id for a global one.
Origin only. The source skill id and version sha are withheld, since a caller reading an organisation listing is not necessarily a member of the project a skill was promoted from.
Absent on a skill that was created at its tier rather than promoted into it.
Project-tier skills are not repeated at the top level
They belong to one project, and appear in that project's resolved set under projects[] — which is where shadowing applies.
The example above is the ordinary case rather than a contrived one: the same name, helper, appears at two tiers, because promotion copies a skill upward and leaves the original in place. So read resolution.tier rather than inferring the tier from the bucket it arrived in.
Two consequences worth designing for:
Both parameters, or neither, is a 422.
That is deliberate rather than lenient: silently preferring one would let you believe you had asked an organisation-wide question and quietly receive a single project.
No limit here
GET /prompts accepts and validates a limit. GET /skills does not — a limit in the query string is ignored rather than rejected, because a project's resolved skill set is bounded by resolution, not by pagination.
Listing requires project membership — being on the project, not merely in its organisation. Super Admins count as members of every project in their organisation.
Organisation scope is filtered by the same rule: you get the projects you can actually open, so an organisation you belong to but whose projects you were never added to returns 200 with an empty projects list, not a 403. "Nothing here" stays distinguishable from "you may not look".
| Status | Meaning |
|---|---|
401 | key missing, invalid or revoked |
403 | not a member of that project, or that organisation |
422 | both scope parameters, or neither |
Hi — ask anything about elsai docs. Mention the product name: elsai ARMS, Prompt Manager, Agent Framework, Core, or elsai Guardrails.