Appearance
Skills API Reference
Naming
Skills follow a GitHub-style owner/name naming convention:
- Frontmatter
name: The short skill name (e.g.,concise-answers) — must match the AgentSkills.io spec: lowercase alphanumeric + hyphens, 1-64 chars. slug/fullName: The canonical identity{alias}/{name}(e.g.,snowtimber/concise-answers) — used in URLs, API identifiers, and display.
Two different users can each own a skill named concise-answers — they are distinguished by their owner/name slug, just like GitHub repos.
Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /skills/create | Required | Create a new skill |
| PUT | /skills/update | Required | Update a skill (by ID or slug) |
| POST | /skills/delete | Required | Delete a skill (by ID or slug) |
| GET | /skills/list | Optional | List skills |
| GET | /skills/{skillId} | Optional | Get skill by ID |
| GET | /skills/s/{owner}/{slug} | Optional | Get skill by slug |
| GET | /skills/{skillId}/SKILL.md | Public* | Raw SKILL.md content |
| GET | /skills/s/{owner}/{slug}/SKILL.md | Public* | Raw SKILL.md by slug |
* Public skills are readable without auth; private skills require owner's bearer token.
Create Skill
POST /skills/create
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
skillMd | string | Yes | Full SKILL.md content (YAML frontmatter + markdown body) |
description | string | No | Override description (defaults to frontmatter description) |
visibility | string | No | "public" (default) or "private" |
Response (201)
json
{
"data": {
"message": "Skill created",
"skill": {
"skillId": "uuid",
"skillName": "concise-answers",
"fullName": "snowtimber/concise-answers",
"description": "Keep responses short...",
"slug": "snowtimber/concise-answers",
"rawUrl": "https://api.universalapi.co/skills/s/snowtimber/concise-answers/SKILL.md",
"visibility": "public",
"status": "active"
}
}
}Update Skill
PUT /skills/update
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
skillId | string | One of skillId/slug | Skill UUID to update |
slug | string | One of skillId/slug | Owner/name slug (e.g., snowtimber/concise-answers) |
skillMd | string | No | New SKILL.md content |
description | string | No | New description |
visibility | string | No | "public" or "private" |
Example — update by slug
bash
curl -X PUT https://api.universalapi.co/skills/update \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"slug": "snowtimber/concise-answers", "visibility": "private"}'Delete Skill
POST /skills/delete
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
skillId | string | One of skillId/slug | Skill UUID to delete |
slug | string | One of skillId/slug | Owner/name slug (e.g., snowtimber/concise-answers) |
Deleting a skill removes its slug from the index, so the same name can be recreated.
List Skills
GET /skills/list?visibility={all|public|private}
Returns all skills visible to the caller. Anonymous users see only public skills.
Raw SKILL.md
GET /skills/s/{owner}/{slug}/SKILL.md
Returns the raw SKILL.md content as text/markdown; charset=utf-8 with a 5-minute cache header. This is the URL you pass to Skill.from_url() in your agent code.