Documentation Index
Fetch the complete documentation index at: https://docs.qoder.com/llms.txt
Use this file to discover all available pages before exploring further.
POST /v1/skills
Uploads and creates a new Skill resource. Skill content must be uploaded as a .zip archive using multipart/form-data encoding.
| Header | Required | Description |
|---|
Authorization | Yes | Bearer $QODER_PAT |
Content-Type | No | Set automatically by curl -F to multipart/form-data; do not specify manually |
Request body (multipart/form-data)
| Field | Type | Required | Description |
|---|
file | file | Yes | .zip archive of skill content (must be zip format) |
name | string | No | Skill name. If omitted, read from the SKILL.md frontmatter inside the zip |
type | string | No | Skill type. One of: custom, prebuilt (default custom) |
description | string | No | Skill description |
Zip file structure
The archive must contain a SKILL.md file in this format:
name: my-skill
description: Skill description
version: 1.0.0
# Skill title
## Steps
1. Step one
2. Step two
Example request
# Prepare skill content
mkdir my-skill && cat > my-skill/SKILL.md << 'EOF'
name: my-custom-skill
description: Custom skill example
version: 1.0.0
# My Custom Skill
## Steps
1. Perform action A
2. Perform action B
## Verification
Confirm the operation completed.
EOF
# Pack as zip
cd my-skill && zip ../my-skill.zip SKILL.md && cd ..
# Upload to create
curl -X POST https://openapi.qoder.sh/api/v1/cloud/skills \
-H "Authorization: Bearer $QODER_PAT" \
-F "name=my-custom-skill" \
-F "type=custom" \
-F "description=Custom skill example" \
-F "file=@my-skill.zip"
Example response
HTTP 201 Created
{
"id": "skill_019e3bba474b73cfaf19eae9b5f5e66d",
"type": "skill",
"name": "my-custom-skill",
"description": "Custom skill example",
"skill_type": "custom",
"status": "active",
"version": 1,
"content_size": 309,
"content_sha256": "f253cb7d35790025f85917c0c239422cff1de067d00278db8897c585a3f28d94",
"metadata": {},
"created_at": "2026-05-18T15:35:24.248164Z",
"updated_at": "2026-05-18T15:35:24.248164Z"
}
Response fields
| Field | Type | Description |
|---|
id | string | Skill unique identifier with the skill_ prefix |
type | string | Always "skill" |
name | string | Skill name |
description | string | Skill description |
skill_type | string | Skill type: custom or prebuilt |
status | string | Status: active |
version | integer | Current version number (starts at 1) |
content_size | integer | Size of the zip content in bytes |
content_sha256 | string | SHA-256 hash of the content |
metadata | object | Custom metadata |
created_at | string | Creation time (ISO 8601) |
updated_at | string | Last update time (ISO 8601) |
Errors
| HTTP | Type | Trigger |
|---|
| 400 | invalid_request_error | Non-multipart request: “Invalid multipart form or request too large.” |
| 400 | invalid_request_error | Missing file field: “Field ‘file’ is required.” |
| 400 | invalid_request_error | Not a zip file: “Only .zip files are accepted.” |
| 401 | TOKEN_INVALID | Missing or invalid authentication token |
Notes
- Duplicate skill names are allowed (uniqueness is not enforced).
- If
name is not in the form, it is read from the SKILL.md frontmatter in the zip.
- Initial version number is 1.
- JSON Content-Type is not supported;
multipart/form-data is required.
See Errors for the full error envelope.