Apps
List the account's published apps (with live-derived URL + blockers), newest first
Opaque cursor (page.nextCursor).
Page size (1–100, default 20).
curl https://api.koo.io/accounts/:accountId/apps \ -H "Authorization: Bearer kc_your_api_token"{ "data": [ { "id": "acct_01example0000000000000000x", "accountId": "acct_01example0000000000000000x", "projectId": "project_01example0000000000000000x", "environmentName": "example", "serviceName": "example", "urlChoice": "example", "slug": "my-app", "profile": { "displayName": "My app", "tagline": "example", "description": "example", "images": [ "https://example.com" ], "youtubeId": "youtube_01example0000000000000000x", "videoCover": true, "category": "example", "tags": [ "example" ], "links": { "website": "https://example.com", "repo": "https://example.com", "appStore": "https://example.com", "playStore": "https://example.com", "steam": "https://example.com" } }, "url": "https://example.com", "blockers": [ "service_missing" ], "createdAt": "2026-01-01T00:00:00.000Z", "updatedAt": "2026-01-01T00:00:00.000Z" } ], "page": { "nextCursor": "example", "hasMore": true }}Publish a service as a showcase app
Validates the pointer live (project in account; environment + exposed web service by name; URL is the generated koo URL or an active custom domain of that service) and the publish gate (tagline + category).
The project the service to publish lives in (must belong to the account).
Name of the environment the service lives in.
Name of the exposed web service to publish (by name).
Either 'generated' (the koo URL from the service's status) or one of the service's active custom domain hostnames.
The public URL slug under the owner handle (url-safe word, 3-16 chars, account-unique).
The initial listing content (tagline + category are required to publish).
Identifier of the published app.
Identifier of the owning account.
Identifier of the project the pointed-at service lives in.
Name of the environment the pointed-at service lives in (by name, not id).
Name of the exposed web service this listing points at (by name, not id).
Either 'generated' (the koo URL from the service's status) or one of the service's active custom domain hostnames.
URL slug of the app under the owner's handle (/@handle/:slug).
The live-derived public URL to visit, when resolvable (absent while degraded with no fallback).
Live-derived degradations on the pointer — the honest reasons shown to the owner. Empty when healthy.
When the app was published.
When the app or its listing was last updated.
curl https://api.koo.io/accounts/:accountId/apps \ -X POST \ -H "Authorization: Bearer kc_your_api_token" \ -H "Content-Type: application/json" \ -d '{ "projectId": "project_01example0000000000000000x", "environmentName": "example", "serviceName": "example", "slug": "my-app", "profile": {} }'{ "id": "acct_01example0000000000000000x", "accountId": "acct_01example0000000000000000x", "projectId": "project_01example0000000000000000x", "environmentName": "example", "serviceName": "example", "urlChoice": "example", "slug": "my-app", "profile": { "displayName": "My app", "tagline": "example", "description": "example", "images": [ "https://example.com" ], "youtubeId": "youtube_01example0000000000000000x", "videoCover": true, "category": "example", "tags": [ "example" ], "links": { "website": "https://example.com", "repo": "https://example.com", "appStore": "https://example.com", "playStore": "https://example.com", "steam": "https://example.com" } }, "url": "https://example.com", "blockers": [ "service_missing" ], "createdAt": "2026-01-01T00:00:00.000Z", "updatedAt": "2026-01-01T00:00:00.000Z"}Get a published app (owner view)
Identifier of the published app.
Identifier of the owning account.
Identifier of the project the pointed-at service lives in.
Name of the environment the pointed-at service lives in (by name, not id).
Name of the exposed web service this listing points at (by name, not id).
Either 'generated' (the koo URL from the service's status) or one of the service's active custom domain hostnames.
URL slug of the app under the owner's handle (/@handle/:slug).
The live-derived public URL to visit, when resolvable (absent while degraded with no fallback).
Live-derived degradations on the pointer — the honest reasons shown to the owner. Empty when healthy.
When the app was published.
When the app or its listing was last updated.
curl https://api.koo.io/accounts/:accountId/apps/:appId \ -H "Authorization: Bearer kc_your_api_token"{ "id": "acct_01example0000000000000000x", "accountId": "acct_01example0000000000000000x", "projectId": "project_01example0000000000000000x", "environmentName": "example", "serviceName": "example", "urlChoice": "example", "slug": "my-app", "profile": { "displayName": "My app", "tagline": "example", "description": "example", "images": [ "https://example.com" ], "youtubeId": "youtube_01example0000000000000000x", "videoCover": true, "category": "example", "tags": [ "example" ], "links": { "website": "https://example.com", "repo": "https://example.com", "appStore": "https://example.com", "playStore": "https://example.com", "steam": "https://example.com" } }, "url": "https://example.com", "blockers": [ "service_missing" ], "createdAt": "2026-01-01T00:00:00.000Z", "updatedAt": "2026-01-01T00:00:00.000Z"}Re-point a published app at a different service and/or URL
Re-validates the resulting pointer live (same rules as publish). A structural change to the public listing, so it requires the publish permission.
New environment name for the pointer.
New exposed web service name for the pointer.
New URL choice ('generated' or an active custom domain hostname).
Identifier of the published app.
Identifier of the owning account.
Identifier of the project the pointed-at service lives in.
Name of the environment the pointed-at service lives in (by name, not id).
Name of the exposed web service this listing points at (by name, not id).
Either 'generated' (the koo URL from the service's status) or one of the service's active custom domain hostnames.
URL slug of the app under the owner's handle (/@handle/:slug).
The live-derived public URL to visit, when resolvable (absent while degraded with no fallback).
Live-derived degradations on the pointer — the honest reasons shown to the owner. Empty when healthy.
When the app was published.
When the app or its listing was last updated.
curl https://api.koo.io/accounts/:accountId/apps/:appId \ -X PATCH \ -H "Authorization: Bearer kc_your_api_token" \ -H "Content-Type: application/json" \ -d '{}'{ "id": "acct_01example0000000000000000x", "accountId": "acct_01example0000000000000000x", "projectId": "project_01example0000000000000000x", "environmentName": "example", "serviceName": "example", "urlChoice": "example", "slug": "my-app", "profile": { "displayName": "My app", "tagline": "example", "description": "example", "images": [ "https://example.com" ], "youtubeId": "youtube_01example0000000000000000x", "videoCover": true, "category": "example", "tags": [ "example" ], "links": { "website": "https://example.com", "repo": "https://example.com", "appStore": "https://example.com", "playStore": "https://example.com", "steam": "https://example.com" } }, "url": "https://example.com", "blockers": [ "service_missing" ], "createdAt": "2026-01-01T00:00:00.000Z", "updatedAt": "2026-01-01T00:00:00.000Z"}Unpublish an app (soft-delete; republish re-creates)
curl https://api.koo.io/accounts/:accountId/apps/:appId \ -X DELETE \ -H "Authorization: Bearer kc_your_api_token"Edit a published app listing (content, tags, links, image order)
Owner/editor edit of the showcase fields (displayName/tagline/description/youtubeId/category/tags/links + image reorder/remove). Adding an image goes through the upload commit (scope appImage). Repopulates discovery search.
Public pretty name (null to clear — the app slug is then shown).
Short one-line summary (null to clear).
Long-form description for the showcase page (null to clear).
YouTube video id embedded as a demo/trailer (null to clear).
When a video is set, use the video's YouTube thumbnail as the cover (true) or fall back to the first gallery image (false).
Discovery category slug; must be one of the configured categories (null to clear).
Freeform discovery tags (empty array to clear).
External links shown on the showcase page (replaces the whole set).
The reordered/pruned gallery (replaces the order; images[0] is the cover). Only URLs already committed to this app may appear — adding a new image goes through the upload commit.
Identifier of the published app.
Identifier of the owning account.
Identifier of the project the pointed-at service lives in.
Name of the environment the pointed-at service lives in (by name, not id).
Name of the exposed web service this listing points at (by name, not id).
Either 'generated' (the koo URL from the service's status) or one of the service's active custom domain hostnames.
URL slug of the app under the owner's handle (/@handle/:slug).
The live-derived public URL to visit, when resolvable (absent while degraded with no fallback).
Live-derived degradations on the pointer — the honest reasons shown to the owner. Empty when healthy.
When the app was published.
When the app or its listing was last updated.
curl https://api.koo.io/accounts/:accountId/apps/:appId/profile \ -X PATCH \ -H "Authorization: Bearer kc_your_api_token" \ -H "Content-Type: application/json" \ -d '{}'{ "id": "acct_01example0000000000000000x", "accountId": "acct_01example0000000000000000x", "projectId": "project_01example0000000000000000x", "environmentName": "example", "serviceName": "example", "urlChoice": "example", "slug": "my-app", "profile": { "displayName": "My app", "tagline": "example", "description": "example", "images": [ "https://example.com" ], "youtubeId": "youtube_01example0000000000000000x", "videoCover": true, "category": "example", "tags": [ "example" ], "links": { "website": "https://example.com", "repo": "https://example.com", "appStore": "https://example.com", "playStore": "https://example.com", "steam": "https://example.com" } }, "url": "https://example.com", "blockers": [ "service_missing" ], "createdAt": "2026-01-01T00:00:00.000Z", "updatedAt": "2026-01-01T00:00:00.000Z"}An account's published apps as discovery cards (fully-broken listings hidden)
curl https://api.koo.io/profiles/:handle/apps \ -H "Authorization: Bearer kc_your_api_token"{ "items": [ { "id": "acct_01example0000000000000000x", "accountId": "acct_01example0000000000000000x", "handle": "alice", "slug": "my-app", "name": "my-app", "tagline": "example", "photoUrl": "https://example.com", "youtubeId": "youtube_01example0000000000000000x", "videoCover": true, "category": "example", "tags": [ "example" ], "region": "example", "score": 1, "createdAt": "2026-01-01T00:00:00.000Z" } ], "nextCursor": "example"}Public app detail — profile, images, derived Visit URL, comments (depth ≤ 1), vote/follow state (when authed)
Identifier of the published app.
Identifier of the owning account.
URL slug of the app under the owner's handle.
Display name of the app (profile displayName, falling back to the slug).
The public URL to visit, or null when the listing is degraded (the Visit CTA is then hidden).
Primary deploy region — the identifier of the app's exposed service's first enabled location (e.g. `aws-us-east-2`); null when the service or its region can no longer be resolved.
Aggregate social counts for the app.
The first page of the app's threaded comments (newest first; replies nest one level via parentId).
The viewing account's current vote (+1 up, -1 down) — present only on an authenticated read with a vote cast.
The viewing account's follow relationship to the author — present only on an authenticated read.
When the app was published.
curl https://api.koo.io/profiles/:handle/apps/:slug \ -H "Authorization: Bearer kc_your_api_token"{ "id": "acct_01example0000000000000000x", "accountId": "acct_01example0000000000000000x", "slug": "my-app", "name": "my-app", "author": { "id": "acct_01example0000000000000000x", "handle": "alice", "displayName": "My app", "avatarUrl": "https://example.com" }, "profile": { "displayName": "My app", "tagline": "example", "description": "example", "images": [ "https://example.com" ], "youtubeId": "youtube_01example0000000000000000x", "videoCover": true, "category": "example", "tags": [ "example" ], "links": { "website": "https://example.com", "repo": "https://example.com", "appStore": "https://example.com", "playStore": "https://example.com", "steam": "https://example.com" } }, "url": "https://example.com", "region": "example", "counts": { "comments": 0, "score": 1 }, "comments": { "data": [ { "id": "acct_01example0000000000000000x", "author": { "id": "acct_01example0000000000000000x", "handle": "alice", "displayName": "My app", "avatarUrl": "https://example.com" }, "body": "example", "score": 1, "viewerVote": -1, "parentId": "parent_01example0000000000000000x", "createdAt": "2026-01-01T00:00:00.000Z", "deletedAt": "2026-01-01T00:00:00.000Z", "replies": { "data": [ { "id": null, "author": null, "body": null, "score": null, "viewerVote": null, "parentId": null, "createdAt": null, "deletedAt": null } ], "page": { "nextCursor": "example", "hasMore": true } }, "replyCount": 0 } ], "page": { "nextCursor": "example", "hasMore": true } }, "viewerVote": -1, "authorFollowState": { "following": true, "followedBy": true }, "createdAt": "2026-01-01T00:00:00.000Z"}