Kosu
Kosu is in beta. The v1 API may change.

API Reference

Base URL: https://usekosu.com/api/v1

All endpoints require a Bearer token. See Authentication.

A note on pagination

Queue items use cursor-based pagination because the queue is drag-reorderable – cursors stay stable as items move. All other states (read, archived, deleted, suggested) use offset-based pagination, sorted by last updated.

Items

Items are URLs in a user's queue.

POST/items

Add a URL to the queue. Kosu canonicalizes the URL, fetches metadata, and deduplicates. If the URL already exists as an active item, returns it unchanged. If archived/read/deleted, reactivates it.

NameTypeRequiredDescription
urlstringYesURL to add (1-2048 chars). Kosu fetches metadata automatically.
titlestringNoOverride auto-fetched title (1-256 chars).
sourcestringNoOverride content type. One of: youtube, podcast, paper, newsletter, repo, article, book, course, other.
thumbnailstringNoOverride thumbnail URL.
channel_namestringNoCreator or channel name.
duration_minutesintegerNoDuration in minutes (0-99999).
curl -X POST https://usekosu.com/api/v1/items \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"}'
{
  "object": "item",
  "id": "itm_abc123",
  "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
  "title": "Rick Astley - Never Gonna Give You Up",
  "source": "youtube",
  "state": "queue",
  "channel_name": "Rick Astley",
  "thumbnail": "https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg",
  "duration": "3m 33s",
  "duration_minutes": 3,
  "created_at": "2026-02-25T10:00:00.000Z",
  "updated_at": "2026-02-25T10:00:00.000Z",
  "opened_at": null,
  "read_at": null,
  "archived_at": null,
  "meta": {
    "created": true,
    "reactivated": false
  }
}

Returns 201 if created or reactivated, 200 if already in queue. Check meta.created and meta.reactivated to distinguish.


GET/items

List items filtered by state. Defaults to queue items.

NameTypeRequiredDescription
statestringNoFilter by state: queue (default), read, archived, deleted, suggested.
limitintegerNoMax items to return. 1-100, default 50.
cursorstringNoPagination cursor (queue state only). Use next_cursor from previous response.
offsetintegerNoPagination offset (non-queue states only).
curl https://usekosu.com/api/v1/items?state=queue&limit=10 \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "object": "list",
  "data": [
    {
      "object": "item",
      "id": "itm_abc123",
      "url": "https://example.com/article",
      "title": "Example Article",
      "source": "article",
      "state": "queue",
      "channel_name": null,
      "thumbnail": null,
      "duration": null,
      "duration_minutes": null,
      "created_at": "2026-02-25T10:00:00.000Z",
      "updated_at": "2026-02-25T10:00:00.000Z",
      "opened_at": null,
      "read_at": null,
      "archived_at": null
    }
  ],
  "has_more": false,
  "next_cursor": null
}

GET/items/:id

Fetch a single item by ID.

curl https://usekosu.com/api/v1/items/itm_abc123 \
  -H "Authorization: Bearer YOUR_API_KEY"

PATCH/items/:id

Update an item. Send exactly one of four update types in the request body.

State transition

Move an item to a new lifecycle state.

NameTypeRequiredDescription
statestringYesTarget state: read, archived, queue (requeue), or suggested (Pro).
reasonstringNoReason for suggesting (only when state is suggested, max 512 chars).
# Mark as read
curl -X PATCH https://usekosu.com/api/v1/items/itm_abc123 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"state": "read"}'

# Archive
curl -X PATCH https://usekosu.com/api/v1/items/itm_abc123 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"state": "archived"}'

# Requeue (restore to bottom of queue)
curl -X PATCH https://usekosu.com/api/v1/items/itm_abc123 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"state": "queue"}'

Record open

Mark the item as opened. This is a passive touch – it extends fade protection by 1 day (max once per 24 hours).

curl -X PATCH https://usekosu.com/api/v1/items/itm_abc123 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"opened": true}'

Reorder

Move an item to a new position using relative positioning. Provide after and/or before to specify placement.

NameTypeRequiredDescription
position.afterstring | nullNoPlace after this item ID. null = move to top.
position.beforestring | nullNoPlace before this item ID. null = move to bottom.
# Move to top of queue
curl -X PATCH https://usekosu.com/api/v1/items/itm_abc123 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"position": {"after": null}}'

# Place after another item
curl -X PATCH https://usekosu.com/api/v1/items/itm_abc123 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"position": {"after": "itm_other456"}}'

Field update

Update metadata fields. At least one field required.

NameTypeRequiredDescription
titlestringNoItem title (1-256 chars).
sourcestringNoContent type.
thumbnailstringNoThumbnail URL.
channel_namestringNoCreator or channel name.
duration_minutesintegerNoDuration in minutes.
curl -X PATCH https://usekosu.com/api/v1/items/itm_abc123 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title": "Better Title", "source": "paper"}'

DELETE/items/:id

Soft-delete an item. Moves to deleted state, recoverable for 30 days. Idempotent.

curl -X DELETE https://usekosu.com/api/v1/items/itm_abc123 \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "object": "item",
  "id": "itm_abc123",
  "state": "deleted",
  "deleted": true
}

Suggestions

Suggest content for a user's review. The user sees suggestions in a separate tab and can accept (move to queue) or dismiss them. Pro feature.

POST/suggestions

Suggest a URL. If the URL is already active in the queue, returns 409. If previously suggested, updates the existing suggestion.

NameTypeRequiredDescription
urlstringYesURL to suggest (1-2048 chars).
reasonstringNoWhy you're suggesting this. Shown to the user (1-512 chars).
titlestringNoOverride title (1-256 chars).
sourcestringNoOverride content type.
thumbnailstringNoOverride thumbnail URL.
channel_namestringNoCreator or channel name.
duration_minutesintegerNoDuration in minutes.
curl -X POST https://usekosu.com/api/v1/suggestions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/distributed-systems-guide",
    "reason": "Relevant to your interest in distributed systems"
  }'
{
  "object": "suggestion",
  "id": "sug_def456",
  "url": "https://example.com/distributed-systems-guide",
  "title": "A Guide to Distributed Systems",
  "source": "article",
  "channel_name": null,
  "thumbnail": null,
  "duration": null,
  "duration_minutes": null,
  "reason": "Relevant to your interest in distributed systems",
  "created_at": "2026-02-25T12:00:00.000Z",
  "updated_at": "2026-02-25T12:00:00.000Z"
}

Returns 201 if created, 200 if updated, 409 if URL is already an active item.


GET/suggestions

List active suggestions.

NameTypeRequiredDescription
limitintegerNoMax suggestions to return. 1-100, default 50.
curl https://usekosu.com/api/v1/suggestions \
  -H "Authorization: Bearer YOUR_API_KEY"

POST/suggestions/:id

Accept or dismiss a suggestion. Accept moves it to the queue. Dismiss soft-deletes it.

NameTypeRequiredDescription
actionstringYesEither "accept" or "dismiss".
# Accept a suggestion
curl -X POST https://usekosu.com/api/v1/suggestions/sug_def456 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"action": "accept"}'

# Dismiss a suggestion
curl -X POST https://usekosu.com/api/v1/suggestions/sug_def456 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"action": "dismiss"}'

Accept returns an Item object. Dismiss returns {"object": "suggestion", "id": "sug_...", "dismissed": true}.


Object reference

Item

NameTypeRequiredDescription
object"item"YesObject type.
idstringYesPrefixed ID (e.g. "itm_abc123").
urlstring | nullYesCanonical URL.
titlestring | nullYesTitle.
sourcestringYesContent type.
statestringYesLifecycle state: queue, suggested, read, archived, deleted.
channel_namestring | nullNoCreator or channel.
thumbnailstring | nullNoThumbnail URL.
durationstring | nullNoHuman-readable duration (e.g. "1h 30m").
duration_minutesinteger | nullNoDuration in minutes.
created_atstringYesISO 8601 timestamp.
updated_atstringYesISO 8601 timestamp.
opened_atstring | nullNoFirst opened timestamp.
read_atstring | nullNoMarked read timestamp.
archived_atstring | nullNoArchived timestamp.

Suggestion

NameTypeRequiredDescription
object"suggestion"YesObject type.
idstringYesPrefixed ID (e.g. "sug_abc123").
urlstring | nullYesCanonical URL.
titlestring | nullYesTitle.
sourcestringYesContent type.
channel_namestring | nullNoCreator or channel.
thumbnailstring | nullNoThumbnail URL.
durationstring | nullNoHuman-readable duration.
duration_minutesinteger | nullNoDuration in minutes.
reasonstring | nullNoWhy this was suggested.
created_atstringYesISO 8601 timestamp.
updated_atstringYesISO 8601 timestamp.

List

NameTypeRequiredDescription
object"list"YesObject type.
dataarrayYesArray of Item or Suggestion objects.
has_morebooleanYesWhether more results exist.
next_cursorstring | nullYesCursor for next page (queue state only).

Error

NameTypeRequiredDescription
error.typestringYesError category.
error.codestringYesMachine-readable error code.
error.messagestringYesHuman-readable description.
error.paramstringNoThe field that caused the error.

© 2026 Kosu