Overview
The OpenCoWork API is a plain REST API. Every endpoint lives under /api/v1 on your deployment origin — set BASE to that origin in the examples below. Responses are JSON with camelCase property names; properties with null values are omitted.
The catalog has four content types — mcp, skill, agent and soul — that share identical read routes: swap the {type} segment and everything else stays the same. Each response carries an x-correlation-id header you can quote when reporting issues.
BASE="https://your-host"
# Liveness
curl "$BASE/health"
# -> ok
# First page of published MCP servers (no auth needed)
curl "$BASE/api/v1/mcp?page=1&pageSize=5"Authentication & rate limits
All catalog read endpoints are public — no credentials needed. Write endpoints (reports, publishing, key management) require an API key. Create one in Console → API Keys; the full token (prefix ock_) is shown exactly once at creation. Send it as a standard bearer token.
API-key requests count against a daily quota shared by all keys of the same account. Every authenticated response returns X-RateLimit-Limit and X-RateLimit-Remaining headers; when the quota is exhausted the API returns 429 until 00:00 UTC. Request a higher quota from the console.
export OCW_KEY="ock_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
curl "$BASE/api/v1/auth/me" \
-H "Authorization: Bearer $OCW_KEY"
# -> { "id": "…", "name": "…", "roles": ["Publisher"], "permissions": […], "isAdmin": false }Errors
Errors use RFC 7807 problem details. The title field carries a stable, dot-separated error code (for example Mcp.NotFound) and detail carries a human-readable message. Match on title, not on detail.
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
"title": "Mcp.NotFound",
"status": 404,
"detail": "MCP server not found."
}| Status | When |
|---|---|
| 400 | Invalid input (error code contains Invalid or NotEditable) |
| 401 | Missing or invalid credentials |
| 404 | Resource not found (code contains NotFound) |
| 409 | Business-rule conflict (default for other error codes) |
| 429 | Daily API-key quota exhausted (ApiKey.QuotaExceeded); resets 00:00 UTC |
Pagination
List endpoints take page (default 1) and pageSize (default 20, max 100) and return a fixed envelope.
{
"items": [ … ],
"page": 1,
"pageSize": 20,
"total": 68,
"hasNext": true
}Catalog (read)
Public, read-only access to published items. Replace {type} with mcp, skill, agent or soul. Item summaries share a common shape (id, slug, name, summary, iconUrl, publisherName, source, isOfficial, isFeatured, installCount, viewCount, ratingAverage, tags, categories, updatedAt, publishedAt); MCP adds primaryTransport and toolCount, Skill adds executesCode.
Version detail is type-specific: MCP versions include connections, tools, resources, prompts, configFields and permissions; Skill versions include bundleFiles, dependencies, examples and parameters; Agent and Soul versions carry metadata only (readme, license, sourceUrl, packageUrl, checksum).
/api/v1/{type}PublicSearch and list published items
Path parameters
| Parameter | Type | Description |
|---|---|---|
{type}required | string | Catalog type: mcp, skill, agent or soul. All four expose the same routes. |
Query parameters
| Parameter | Type | Description |
|---|---|---|
search | string | Full-text search over name and description. |
category | string | Category slug (see the categories endpoint). |
tag | string | Tag slug. |
source | string | official or user. |
sort | string | popular | mostusage | rating | featured | latest; anything else sorts by publish date (newest first). |
page | int | 1-based page number. |
pageSize | int | 1–100, default 20. |
curl "$BASE/api/v1/mcp?search=github&sort=popular&pageSize=3"/api/v1/{type}/categoriesPublicList categories with published-item counts
Path parameters
| Parameter | Type | Description |
|---|---|---|
{type}required | string | Catalog type: mcp, skill, agent or soul. All four expose the same routes. |
[
{ "slug": "developer", "name": "Developer Tools", "count": 37 },
{ "slug": "productivity", "name": "Productivity", "count": 16 }
]/api/v1/{type}/{slug}PublicGet item detail by slug
Returns full metadata plus stats (viewCount, installCount, usageCount, favoriteCount, ratingCount, ratingAverage) and currentVersion — the published version detail.
Path parameters
| Parameter | Type | Description |
|---|---|---|
{type}required | string | Catalog type: mcp, skill, agent or soul. All four expose the same routes. |
slugrequired | string | Item slug. |
curl "$BASE/api/v1/skill/pdf-processing"/api/v1/soul/{slug}/prompt.txtPublicSoul persona prompt as Markdown
Soul only. One-request persona adoption for AI agents: returns Markdown (Content-Type: text/markdown) with the soul name, summary, and published SOUL.md body (falls back to description). The web app mirrors it at /soul/{slug}/prompt.txt.
Open example prompt.txtPath parameters
| Parameter | Type | Description |
|---|---|---|
slugrequired | string | Soul slug. |
curl -i "$BASE/api/v1/soul/seneca-stoic/prompt.txt"
# Content-Type: text/markdown; charset=utf-8
#
# # Seneca
# > Stoic mentor persona
#
# You are Seneca…/api/v1/{type}/{slug}/versionsPublicList version history
Path parameters
| Parameter | Type | Description |
|---|---|---|
{type}required | string | Catalog type: mcp, skill, agent or soul. All four expose the same routes. |
slugrequired | string | Item slug. |
/api/v1/{type}/{slug}/versions/{version}PublicGet one version in full detail
Path parameters
| Parameter | Type | Description |
|---|---|---|
{type}required | string | Catalog type: mcp, skill, agent or soul. All four expose the same routes. |
slugrequired | string | Item slug. |
versionrequired | string | Version string, e.g. 1.2.0. |
/api/v1/{type}/{slug}/reportAPI keyReport a published item
Path parameters
| Parameter | Type | Description |
|---|---|---|
{type}required | string | Catalog type: mcp, skill, agent or soul. All four expose the same routes. |
slugrequired | string | Item slug. |
Request body
| Parameter | Type | Description |
|---|---|---|
reasonrequired | string | Why the item is being reported. |
detail | string | Optional extra context. |
Telemetry
If you redistribute catalog items (an IDE plugin, an agent runtime, a proxy), report usage events so install and usage counts stay meaningful. The endpoint is anonymous. clientId is any stable opaque string for the end device; the server stores only a truncated SHA-256 of it (or of the caller IP when omitted) for deduplication — never the raw value.
/api/v1/telemetryPublicRecord a view / install / usage / favorite event
Request body
| Parameter | Type | Description |
|---|---|---|
itemTyperequired | string | mcp | skill | agent | soul. |
slugrequired | string | Item slug. |
eventTyperequired | string | view | install (a download) | usage (a real invocation) | favorite. |
versionId | uuid | Optional version id the event applies to. |
toolName | string | For MCP usage events: the tool that was invoked. |
clientId | string | Stable opaque device identifier (hashed server-side). |
curl -X POST "$BASE/api/v1/telemetry" \
-H "Content-Type: application/json" \
-d '{ "itemType": "mcp", "slug": "github-mcp", "eventType": "install", "clientId": "device-8f2c" }'
# -> { "recorded": true }API keys
Manage the keys of the authenticated account. Any authenticated caller (console session or an existing API key) may use these.
/api/v1/api-keysAPI key / sessionList keys (prefix, status, usage — never the token)
/api/v1/api-keysAPI key / sessionCreate a key; the full ock_ token is returned once
Request body
| Parameter | Type | Description |
|---|---|---|
namerequired | string | Display name for the key. |
/api/v1/api-keys/usageAPI key / sessionDaily usage vs. quota
Query parameters
| Parameter | Type | Description |
|---|---|---|
days | int | How many trailing days to include. |
/api/v1/api-keys/quota-requestsAPI key / sessionRequest a higher daily quota (max 1,000,000)
Request body
| Parameter | Type | Description |
|---|---|---|
requestedQuotarequired | int | Requested daily quota. |
reason | string | Why you need it. |
/api/v1/api-keys/{keyId}/enableAPI key / sessionEnable a key
/api/v1/api-keys/{keyId}/disableAPI key / sessionDisable a key
/api/v1/api-keys/{keyId}API key / sessionDelete a key permanently
Publishing
Programmatic publishing requires the Publisher role on your account. The flow for every type: create a draft (with its first version) → update the draft → add versions → submit for review → moderators approve or request changes → withdraw at any time before a decision. Item status moves through draft → in_review → published (or changes_requested / rejected).
Skills are upload-only: after creating a version, upload the .zip package; SKILL.md inside the bundle is parsed at submit time.
/api/v1/publisher/{type}/minePublisherList your items of this type
Path parameters
| Parameter | Type | Description |
|---|---|---|
{type}required | string | Catalog type: mcp, skill, agent or soul. All four expose the same routes. |
/api/v1/publisher/{type}/draftsPublisherCreate a draft with its first version
Path parameters
| Parameter | Type | Description |
|---|---|---|
{type}required | string | Catalog type: mcp, skill, agent or soul. All four expose the same routes. |
Request body
| Parameter | Type | Description |
|---|---|---|
slugrequired | string | Unique item slug. |
namerequired | string | Display name. |
summaryrequired | string | One-line summary. |
descriptionrequired | string | Long description. |
publisherSlugrequired | string | Your publisher slug. |
tags | string[] | Tag slugs. |
categories | string[] | Category slugs. |
versionrequired | object | First version payload (version, changelog, readme, license, sourceUrl, …; MCP adds connections/tools/…, Skill adds dependencies/examples/parameters). |
/api/v1/publisher/{type}/{id}/draftPublisherUpdate draft metadata
Path parameters
| Parameter | Type | Description |
|---|---|---|
{type}required | string | Catalog type: mcp, skill, agent or soul. All four expose the same routes. |
/api/v1/publisher/{type}/{id}/versionsPublisherAdd a new version
Path parameters
| Parameter | Type | Description |
|---|---|---|
{type}required | string | Catalog type: mcp, skill, agent or soul. All four expose the same routes. |
/api/v1/publisher/skill/{skillId}/versions/{versionId}/packagePublisherUpload a Skill package (multipart, field name file)
Skill only. Send multipart/form-data with a single file field containing the .zip bundle.
curl -X POST "$BASE/api/v1/publisher/skill/$SKILL_ID/versions/$VERSION_ID/package" \
-H "Authorization: Bearer $OCW_KEY" \
-F "file=@my-skill.zip"/api/v1/publisher/{type}/{id}/submit-reviewPublisherSubmit the draft for review
Path parameters
| Parameter | Type | Description |
|---|---|---|
{type}required | string | Catalog type: mcp, skill, agent or soul. All four expose the same routes. |
Request body
| Parameter | Type | Description |
|---|---|---|
comment | string | Optional note to reviewers. |
/api/v1/publisher/{type}/{id}/withdrawPublisherWithdraw a pending submission
Path parameters
| Parameter | Type | Description |
|---|---|---|
{type}required | string | Catalog type: mcp, skill, agent or soul. All four expose the same routes. |