API Reference

Integrate the OpenCoWork catalog — MCP servers, Skills, Agents and Souls — into your product with a plain REST + JSON API.

Download OpenAPI specImport openapi.json into Postman, Insomnia or a client generator.

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.

Quick check
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.

Authenticate and verify
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.

Error response
{
  "type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
  "title": "Mcp.NotFound",
  "status": 404,
  "detail": "MCP server not found."
}
StatusWhen
400Invalid input (error code contains Invalid or NotEditable)
401Missing or invalid credentials
404Resource not found (code contains NotFound)
409Business-rule conflict (default for other error codes)
429Daily 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.

Paged 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).

GET/api/v1/{type}Public

Search and list published items

Path parameters

ParameterTypeDescription
{type}requiredstringCatalog type: mcp, skill, agent or soul. All four expose the same routes.

Query parameters

ParameterTypeDescription
searchstringFull-text search over name and description.
categorystringCategory slug (see the categories endpoint).
tagstringTag slug.
sourcestringofficial or user.
sortstringpopular | mostusage | rating | featured | latest; anything else sorts by publish date (newest first).
pageint1-based page number.
pageSizeint1–100, default 20.
bash
curl "$BASE/api/v1/mcp?search=github&sort=popular&pageSize=3"
GET/api/v1/{type}/categoriesPublic

List categories with published-item counts

Path parameters

ParameterTypeDescription
{type}requiredstringCatalog type: mcp, skill, agent or soul. All four expose the same routes.
Response (excerpt)
[
  { "slug": "developer", "name": "Developer Tools", "count": 37 },
  { "slug": "productivity", "name": "Productivity", "count": 16 }
]
GET/api/v1/{type}/{slug}Public

Get item detail by slug

Returns full metadata plus stats (viewCount, installCount, usageCount, favoriteCount, ratingCount, ratingAverage) and currentVersion — the published version detail.

Path parameters

ParameterTypeDescription
{type}requiredstringCatalog type: mcp, skill, agent or soul. All four expose the same routes.
slugrequiredstringItem slug.
bash
curl "$BASE/api/v1/skill/pdf-processing"
GET/api/v1/soul/{slug}/prompt.txtPublic

Soul 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.txt

Path parameters

ParameterTypeDescription
slugrequiredstringSoul slug.
bash
curl -i "$BASE/api/v1/soul/seneca-stoic/prompt.txt"
# Content-Type: text/markdown; charset=utf-8
#
# # Seneca
# > Stoic mentor persona
#
# You are Seneca…
GET/api/v1/{type}/{slug}/versionsPublic

List version history

Path parameters

ParameterTypeDescription
{type}requiredstringCatalog type: mcp, skill, agent or soul. All four expose the same routes.
slugrequiredstringItem slug.
GET/api/v1/{type}/{slug}/versions/{version}Public

Get one version in full detail

Path parameters

ParameterTypeDescription
{type}requiredstringCatalog type: mcp, skill, agent or soul. All four expose the same routes.
slugrequiredstringItem slug.
versionrequiredstringVersion string, e.g. 1.2.0.
POST/api/v1/{type}/{slug}/reportAPI key

Report a published item

Path parameters

ParameterTypeDescription
{type}requiredstringCatalog type: mcp, skill, agent or soul. All four expose the same routes.
slugrequiredstringItem slug.

Request body

ParameterTypeDescription
reasonrequiredstringWhy the item is being reported.
detailstringOptional 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.

POST/api/v1/telemetryPublic

Record a view / install / usage / favorite event

Request body

ParameterTypeDescription
itemTyperequiredstringmcp | skill | agent | soul.
slugrequiredstringItem slug.
eventTyperequiredstringview | install (a download) | usage (a real invocation) | favorite.
versionIduuidOptional version id the event applies to.
toolNamestringFor MCP usage events: the tool that was invoked.
clientIdstringStable opaque device identifier (hashed server-side).
bash
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.

GET/api/v1/api-keysAPI key / session

List keys (prefix, status, usage — never the token)

POST/api/v1/api-keysAPI key / session

Create a key; the full ock_ token is returned once

Request body

ParameterTypeDescription
namerequiredstringDisplay name for the key.
GET/api/v1/api-keys/usageAPI key / session

Daily usage vs. quota

Query parameters

ParameterTypeDescription
daysintHow many trailing days to include.
POST/api/v1/api-keys/quota-requestsAPI key / session

Request a higher daily quota (max 1,000,000)

Request body

ParameterTypeDescription
requestedQuotarequiredintRequested daily quota.
reasonstringWhy you need it.
POST/api/v1/api-keys/{keyId}/enableAPI key / session

Enable a key

POST/api/v1/api-keys/{keyId}/disableAPI key / session

Disable a key

DELETE/api/v1/api-keys/{keyId}API key / session

Delete 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.

GET/api/v1/publisher/{type}/minePublisher

List your items of this type

Path parameters

ParameterTypeDescription
{type}requiredstringCatalog type: mcp, skill, agent or soul. All four expose the same routes.
POST/api/v1/publisher/{type}/draftsPublisher

Create a draft with its first version

Path parameters

ParameterTypeDescription
{type}requiredstringCatalog type: mcp, skill, agent or soul. All four expose the same routes.

Request body

ParameterTypeDescription
slugrequiredstringUnique item slug.
namerequiredstringDisplay name.
summaryrequiredstringOne-line summary.
descriptionrequiredstringLong description.
publisherSlugrequiredstringYour publisher slug.
tagsstring[]Tag slugs.
categoriesstring[]Category slugs.
versionrequiredobjectFirst version payload (version, changelog, readme, license, sourceUrl, …; MCP adds connections/tools/…, Skill adds dependencies/examples/parameters).
PUT/api/v1/publisher/{type}/{id}/draftPublisher

Update draft metadata

Path parameters

ParameterTypeDescription
{type}requiredstringCatalog type: mcp, skill, agent or soul. All four expose the same routes.
POST/api/v1/publisher/{type}/{id}/versionsPublisher

Add a new version

Path parameters

ParameterTypeDescription
{type}requiredstringCatalog type: mcp, skill, agent or soul. All four expose the same routes.
POST/api/v1/publisher/skill/{skillId}/versions/{versionId}/packagePublisher

Upload a Skill package (multipart, field name file)

Skill only. Send multipart/form-data with a single file field containing the .zip bundle.

bash
curl -X POST "$BASE/api/v1/publisher/skill/$SKILL_ID/versions/$VERSION_ID/package" \
  -H "Authorization: Bearer $OCW_KEY" \
  -F "file=@my-skill.zip"
POST/api/v1/publisher/{type}/{id}/submit-reviewPublisher

Submit the draft for review

Path parameters

ParameterTypeDescription
{type}requiredstringCatalog type: mcp, skill, agent or soul. All four expose the same routes.

Request body

ParameterTypeDescription
commentstringOptional note to reviewers.
POST/api/v1/publisher/{type}/{id}/withdrawPublisher

Withdraw a pending submission

Path parameters

ParameterTypeDescription
{type}requiredstringCatalog type: mcp, skill, agent or soul. All four expose the same routes.