Skip to main content

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.

Headers

HeaderRequiredDescription
AuthorizationYesBearer $QODER_PAT
Content-TypeNoSet automatically by curl -F to multipart/form-data; do not specify manually

Request body (multipart/form-data)

FieldTypeRequiredDescription
filefileYes.zip archive of skill content (must be zip format)
namestringNoSkill name. If omitted, read from the SKILL.md frontmatter inside the zip
typestringNoSkill type. One of: custom, prebuilt (default custom)
descriptionstringNoSkill 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

FieldTypeDescription
idstringSkill unique identifier with the skill_ prefix
typestringAlways "skill"
namestringSkill name
descriptionstringSkill description
skill_typestringSkill type: custom or prebuilt
statusstringStatus: active
versionintegerCurrent version number (starts at 1)
content_sizeintegerSize of the zip content in bytes
content_sha256stringSHA-256 hash of the content
metadataobjectCustom metadata
created_atstringCreation time (ISO 8601)
updated_atstringLast update time (ISO 8601)

Errors

HTTPTypeTrigger
400invalid_request_errorNon-multipart request: “Invalid multipart form or request too large.”
400invalid_request_errorMissing file field: “Field ‘file’ is required.”
400invalid_request_errorNot a zip file: “Only .zip files are accepted.”
401TOKEN_INVALIDMissing 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.