Chataway Developers
Reference

Store API

The public HTTP endpoints of the Chataway store at chataway.co — catalog, app details, bundles and assets, signatures and revocations, publishing and review status.

Base URL: https://chataway.co. Responses are JSON unless noted. Public endpoints need no authentication and allow cross-origin requests.

Most developers only need the CLI, which wraps the publishing endpoints. These are here for tooling, CI, and anyone who wants to show their listing on their own site.

#Catalog

#GET /api/apps/catalog

Listed apps with a published version.

Query
qSearch text (name, description, publisher).
categoryOne of the categories.
json
{
  "apps": [
    {
      "appId": "com.example.acme-assets",
      "name": "Acme Assets",
      "tagline": "Upload images and audio from your chats to your Acme library.",
      "description": "Upload images and audio from your chats to your Acme library.",
      "categories": ["media", "games"],
      "publisher": { "slug": "acme", "name": "Acme Inc.", "verified": true, "website": "https://example.com" },
      "version": "1.2.0",
      "publishedAt": "2026-09-30T10:12:00.000Z",
      "iconUrl": "https://chataway.co/api/apps/com.example.acme-assets/versions/1.2.0/files/assets/icon.png",
      "markUrl": "https://chataway.co/api/apps/com.example.acme-assets/versions/1.2.0/files/assets/mark.svg",
      "accent": "#2F7BF6",
      "screenshots": ["https://chataway.co/api/apps/…/files/assets/s1.png"],
      "permissions": ["Receive images and audio you choose to upload to Acme"],
      "grants": ["files:receive", "host:media"],
      "domains": ["apps.example.com", "cdn.example.com"],
      "accounts": [{ "id": "acme", "label": "Acme", "scopes": ["openid", "asset:write"], "required": true }],
      "tools": [{ "id": "upload_decals", "name": "Upload decals", "description": "…" }],
      "installs": 1204,
      "rating": { "average": 4.6, "count": 38 },
      "homepage": "https://example.com/chataway",
      "support": "mailto:help@example.com",
      "size": 214318
    }
  ]
}

The tagline is the first sentence of your description (≤ 100 characters). Cached for 30 seconds.

#GET /api/apps/:appId

One app: everything in the catalog entry, plus versions (published versions, newest first) and readme (your README.md).

json
{
  "appId": "com.example.acme-assets",
  "…": "…",
  "readme": "# Acme Assets\n…",
  "versions": [
    {
      "version": "1.2.0",
      "publishedAt": "2026-09-30T10:12:00.000Z",
      "changelog": "## 1.2.0\n- Audio uploads",
      "sha256": "9c1f…",
      "size": 214318,
      "signature": "base64…",
      "keyId": "k1",
      "grants": ["files:receive", "host:media"],
      "domains": ["apps.example.com", "cdn.example.com"],
      "accounts": ["acme", "acme:openid", "acme:asset:write"],
      "bundleUrl": "https://chataway.co/api/apps/com.example.acme-assets/versions/1.2.0/bundle"
    }
  ]
}

#GET /api/apps/:appId/versions/:version/bundle

The signed .chataway-app zip. Headers:

Header
X-Chataway-Sha256SHA-256 of the zip (hex).
X-Chataway-SignatureEd25519 signature (base64) over the signed facts.
X-Chataway-Key-IdWhich store key signed it.
X-Chataway-Published-AtPublication time (part of the signed facts).

#GET /api/apps/:appId/versions/:version/files/*path

One file out of a published bundle — your icon, mark and screenshots. Served with a restrictive CSP (an SVG can't run script) and cached for a day. Use these URLs to show your listing art on your own site.

#GET /api/apps/:appId/reviews

Ratings and reviews for an app.

#Signatures and revocations

#GET /api/apps/public-key

json
{ "keyId": "k1", "publicKeyPem": "-----BEGIN PUBLIC KEY-----\n…" }

Chataway pins this key. Every published version is signed with Ed25519 over the canonical JSON (sorted keys, no whitespace) of:

json
{ "accounts": ["acme", "acme:asset:write", "acme:openid"], "appId": "com.example.acme-assets",
  "domains": ["apps.example.com", "cdn.example.com"], "grants": ["files:receive", "host:media"],
  "publishedAt": "2026-09-30T10:12:00.000Z", "sha256": "9c1f…", "version": "1.2.0" }

domains includes your mcpUrl host; lists are sorted, domains lowercased. The desktop installer refuses bundles whose hash, signature or signed facts don't match the manifest inside.

#GET /api/apps/revocations

The yanked versions, signed the same way. Every Mac checks it hourly and at startup, and disables listed versions.

json
{
  "entries": [{ "appId": "com.example.acme-assets", "version": "1.1.0", "reason": "Uploads went to the wrong account", "at": "2026-09-29T08:00:00.000Z" }],
  "signedAt": "2026-09-30T10:00:00.000Z",
  "signature": "base64…"
}

#Publishing

These need a developer token (Authorization: Bearer cwd_…) from chataway login or the developer dashboard.

#POST /api/apps/publish

The request body is the bundle zip (Content-Type: application/zip; up to 25 MiB). At most 20 uploads per 10 minutes.

bash
curl -X POST https://chataway.co/api/apps/publish \
  -H "Authorization: Bearer $CHATAWAY_TOKEN" \
  -H "Content-Type: application/zip" \
  --data-binary @dist/com.example.acme-assets-1.2.0.chataway-app

201 response:

json
{
  "appId": "com.example.acme-assets",
  "version": "1.2.0",
  "status": "in_review",
  "reasons": ["permissions-widened"],
  "issues": [],
  "permissionDiff": { "grantsAdded": [], "domainsAdded": ["cdn.example.com"], "accountsAdded": [], "fileParamsAdded": [], "requiresAdded": [], "widens": true, "…": "…" },
  "reviewUrl": "https://chataway.co/dashboard/developer/apps/com.example.acme-assets"
}

status is published when the version was auto-approved, in_review when it waits for a person. reasons says why: first-version, permissions-widened, publisher-unverified, flagged:<code>.

Errors:

Statuscode
400empty_bodyNo bundle in the body.
400invalid_bundleNot a readable zip (with issues).
401unauthorizedMissing or invalid developer token.
403not_a_memberYou're not a member of the manifest's publisher.
403publisher_suspended, app_suspended
404unknown_publisherCreate the publisher in the developer dashboard first.
409id_takenThe app id belongs to another publisher.
409version_not_greaterversion must be greater than every version you've uploaded (with latest).
413Over 25 MiB.
422validation_failedThe store checks failed; see issues.
429Too many uploads; slow down.

#GET /api/apps/:appId/versions/:version/status

json
{ "appId": "com.example.acme-assets", "version": "1.2.0", "status": "rejected", "issues": [], "notes": "The confirm card doesn't say uploads are public." }

Statuses: submitted → checking → in_review → approved / rejected → published → yanked. See Publishing.

#Device sign-in

What chataway login uses:

POST /api/developer/device/start→ { deviceCode, userCode, verifyUrl, interval, expiresIn }. Codes live 10 minutes.
POST /api/developer/device/poll { deviceCode }→ { token } once approved, { pending: true } before, 403 access_denied if denied in the browser, 410 expired when the code expired. Poll every interval seconds.

#Connected-account relay

Used by Chataway, not by your app — listed so you know what your OAuth server talks to:

GET /apps/oauth/callback?state&codeThe redirect URI you register. Parks the code for 5 minutes and shows "You can close this tab".
GET /api/apps/oauth/result?state=The Mac collects the code, once.

See Connected accounts.