Forward API reference.
Skill object
Create, get, and list endpoints return this structure. content and content_encoding are included only when Get a Skill is called with include_content=true.
| Field | Type | Description |
|---|---|---|
id | string | Skill ID with the skill_ prefix |
type | string | Always "skill" |
display_title | string | Display title, which can be set independently of name in the Skill package. Duplicate values are allowed for the same user |
source | string | Skill source: custom or qoder |
latest_version | string | null | Latest version identifier with three states: • After versioning, a Unix microsecond timestamp such as 1759178010641129;• During migration before backfill, a legacy incremental counter such as 2;• null after all versions are deleted.It is not guaranteed to be incrementable with +1; clients must not use it to predict the next version |
metadata | object | Custom metadata stored with the Skill; defaults to {} when omitted. created_by is reserved by Forward and must not be supplied by callers |
created_at | string | Creation time in RFC 3339 format |
updated_at | string | Last update time in RFC 3339 format |
identity_id | string | null | Owning Forward identity; typically null when created with a PAT |
icon_url | string | null | Icon URL associated by Forward |
binding_info | Binding info | Binding information, such as Template reference counts |
description | string | Skill description. ⚠️ Deprecated: New clients should read it from the version object; see Skill version object. Retained only for compatibility |
content | string | ⚠️ Deprecated: Base64-encoded zip content returned with include_content=true. Use the version-content download endpoint instead |
content_encoding | string | ⚠️ Deprecated: Returned with content and always set to "base64". Use the version-content download endpoint instead |
Skill version object
List Skill Versions, Get a Skill Version, and Create a Skill Version return this structure. Retrieve version content with Download Skill Version Content, and soft-delete an existing version with Delete a Skill Version. A version is immutable after creation and is an independent snapshot of content and metadata.
| Field | Type | Description |
|---|---|---|
id | string | Skill Version ID with the skillver_ prefix |
skill_id | string | Owning Skill ID |
version | string | Version number. New versions return a 16-digit Unix microsecond timestamp; the three states of latest_version use the same value domain |
name | string | Canonical name parsed from name in the uploaded package's SKILL.md frontmatter |
description | string | Description parsed from description in the uploaded package's SKILL.md frontmatter |
directory | string | Top-level package directory name, equal to name |
content_size | integer | Version package size in bytes, up to 50 MB |
content_sha256 | string | SHA-256 digest of the version package content, in lowercase hexadecimal |
status | string | Version status; currently always active |
created_at | string | Creation time in RFC 3339 format |
metadata | object | Version-level metadata; currently always {} |
Legacy version-number compatibility
The {version} path segment in GET /skills/{id}/versions/{version} accepts two forms:
- Recommended: A 16-digit Unix microsecond timestamp such as
1759178010641129. - Compatibility: Legacy incremental counters such as
"1"or"2"still resolve to the same version during migration. A nonexistent legacy number returns404.
latest is not supported and returns 400 invalid_request_error. Call Get a Skill, read latest_version, and use that value in the path. Both Download Skill Version Content and Get a Skill Version follow this rule.
Binding info
Reference summary included by Forward in Skill responses.
| Field | Type | Description |
|---|---|---|
agent_template_count | integer | Number of Templates currently bound to the Skill |
Skill package (upload rules)
Create a Skill and Create a Skill Version upload content with multipart/form-data. The recommended field is files. file is retained for compatibility (⚠️ deprecated; matching requests return Deprecation: true in the response headers). Migrate to files.
Two upload forms are supported:
① Single .zip archive
Upload one files part with Content-Type: application/zip. See "Package structure example" below.
② Bare file tree
The files field can appear multiple times, with one file per part. Each part's filename carries a relative path, such as code-review/SKILL.md or code-review/scripts/run.sh. Forward normalizes parts independently of their order, packages them, and stores the result as a zip archive.
| Rule | Description |
|---|---|
| Upload field | files (repeatable parts); file (deprecated compatibility field for one zip archive) |
| Size limit | Both the compressed archive and its extracted contents must be no larger than 50 MB. Exceeding either limit returns 400 skill_content_too_large. Both the declared extracted size and actual extracted bytes are validated |
| Package manifest | Required SKILL.md under the top-level directory, with name and description in its frontmatter |
| Top-level directory | Exactly one; its directory name must match name in SKILL.md |
Package structure example
List pagination fields
Skill list responses use the same pagination fields as other Forward list endpoints.
| Field | Type | Description |
|---|---|---|
data | array of Skill objects | Records on the current page |
has_more | boolean | Whether another page is available |
next_page | string | null | Forward cursor for the next page (recommended). Equals the current page's last_id when has_more=true; otherwise null |
first_id | string | null | ID of the first record on the current page |
last_id | string | null | ID of the last record on the current page |
page, after_id, and before_id are mutually exclusive; providing more than one returns 400. Use page where possible; it has the same semantics as after_id.
Skill version list pagination fields
Skill version list responses use only the recommended pagination fields.
| Field | Type | Description |
|---|---|---|
data | array of Skill version objects | Records on the current page |
has_more | boolean | Whether another page is available |
next_page | string | Forward cursor for the next page; omitted when has_more=false |