Python 88.3%
TypeScript 7.6%
Shell 4.1%
1# Skills API (`/v1/skills`) — versioned skill bundles for hosted shell and containers23**Status:** DOCUMENTED · LIVE_VERIFIED for create / retrieve / list / content / version create / delete (2026-09-18) · **FAILED_VERIFICATION** for `GET …/versions` (empty list), `GET|DELETE …/versions/{version}` and `POST /v1/skills/{skill_id}` (404 "version not found") — see discrepancies. `GET …/versions/{version}/content` DOCUMENTED (not called).4**Sources:** https://developers.openai.com/api/reference/resources/skills · https://developers.openai.com/api/docs/guides/tools-skills · openapi-master.yaml paths `/skills*`, schemas `CreateSkillBody`, `CreateSkillVersionBody`, `SetDefaultSkillVersionBody`, `SkillResource`, `SkillVersionResource`, `DeletedSkillResource`, `DeletedSkillVersionResource`5**Last verified:** 2026-09-18 · fragment: `generated/fragments/endpoints/openai-containers-skills.json`67## Endpoints89| Method / path | operationId | Body / query | Response | Live 2026-09-18 |10|---|---|---|---|---|11| `POST /v1/skills` | CreateSkill | multipart `files` = one zip **or** `files[]` directory upload (≤ 500 files) | `skill` | 200 (zip; `default_version: "1"`, `latest_version: "1"`) |12| `GET /v1/skills` | ListSkills | `limit`, `order` asc\|desc, `after` | `{object:"list", data[], first_id, last_id, has_more}` | 200 but `data: []` right after creating a skill (3 runs) |13| `GET /v1/skills/{skill_id}` | GetSkill | | `skill` | 200 |14| `POST /v1/skills/{skill_id}` | UpdateSkillDefaultVersion | JSON `{default_version*: "<n>"}` | `skill` | **404** "Skill version '2' was not found" immediately after version 2 was created |15| `DELETE /v1/skills/{skill_id}` | DeleteSkill | | `{object:"skill.deleted", deleted:true, id}` | 200 |16| `GET /v1/skills/{skill_id}/content` | GetSkillContent | | `application/zip` | 200 (`PK` header) |17| `POST /v1/skills/{skill_id}/versions` | CreateSkillVersion | multipart `files` (+ `default` boolean) | `skill.version` (`version: "2"`, `id: skillver_…`) | 200 |18| `GET /v1/skills/{skill_id}/versions` | ListSkillVersions | `limit`, `order`, `after` (version **id**) | list of `skill.version` | 200 but `data: []` (3 runs, even after version 2 existed) |19| `GET /v1/skills/{skill_id}/versions/{version}` | GetSkillVersion | | `skill.version` | **404** for `/versions/1` |20| `DELETE /v1/skills/{skill_id}/versions/{version}` | DeleteSkillVersion | | `{object:"skill.version.deleted", deleted, id, version}` | **404** for `/versions/1` (default version is documented as non-deletable anyway) |21| `GET /v1/skills/{skill_id}/versions/{version}/content` | GetSkillVersionContent | | `application/zip` | not called |2223SDK (Node, verified): `client.skills.create({files})`, `.retrieve`, `.list`, `.delete`, `client.skills.versions.create/list`, `client.skills.content.retrieve` (returns a `Response`, `content-type: application/zip`). Python SDK 3.16.2 exposes `client.skills.*` too (example uses raw HTTP).2425## Objects (live)2627```json28{"id":"skill_…","object":"skill","created_at":1789782267,"name":"atlas-hello","description":"Atlas test skill. Prints OK when asked.","default_version":"1","latest_version":"1"}29{"id":"skillver_…","object":"skill.version","created_at":1789782269,"skill_id":"skill_…","version":"2","name":"atlas-hello","description":"…"}30```31`name`/`description` come from the `SKILL.md` frontmatter inside the zip (`atlas-hello/SKILL.md`).3233## Discrepancies / uncertainties (recorded verbatim)34351. `GET /v1/skills` and `GET /v1/skills/{id}/versions` returned empty `data` in every run (sh, py, ts, probe) although `GET /v1/skills/{id}` succeeded and versions were created. Possible eventual consistency of list indexes or a scoping difference (project vs org) — not resolved.362. Version endpoints addressed by **number** (`/versions/1`, `default_version: "2"`) returned 404 seconds after creation. Whether they expect the `skillver_…` id or need propagation time is unknown; the spec describes `{version}` as "the version number".373. Curl uploads must **not** send `Content-Type: application/json` (the repo `oai` helper does) → `unsupported_content_type`; use plain `curl -F files=@skill.zip`.3839## Bundle rules (docs)4041Exactly one `SKILL.md`/`skill.md`; ≤ 500 files per version; ≤ 25 MB uncompressed; versions immutable; `default_version` used when the reference omits `version`; you cannot delete the default version. Usage in Responses: [skills](../tools/openai/skills.md).4243Examples: `examples/openai/tools/skills/` (sh/py/ts, all cleaned up their skills). Raw: `tmp-live/tools/skill_*.json`.44