TextShelf

Developers Beta

The API

A script or an LLM agent can act as you on textshelf.com with an access token. This page covers getting a token, sending it, and the endpoint to start from. It is the public half of docs/AGENT_API.md; change them together.

Get a token

API access is part of the Standard and Organization plans. On the Free plan the page won't issue a token, and a token issued while subscribed stops working if the subscription ends.

  1. Signed in, open Account → Access tokens (/users/~tokens/), name the token, choose its scopes and when it expires, and copy the key. It is shown once. An account can hold ten active tokens.
  2. Send it on every request:

text Authorization: Bearer ts_…

The request is then made as you. A token also exempts the request from CSRF checks, so a JSON POST needs no cookie. Don't post to the sign-in form from a script.

A token is accepted on /api/, /notate/api/ and /registry/api/ only. Anywhere else, an HTML page or the admin, it is refused with not_an_api_path, whatever its scopes. Changing your password revokes every token on the account. Creating a token emails you its name and first characters, never the key. Only a SHA-256 of the key is kept: if you lose it, revoke it and issue another.

Scopes: read allows GET, HEAD and OPTIONS; write allows everything.

Refusals

Every refusal is JSON with an error:

Status error Meaning
401 invalid_token Missing, revoked, expired or wrong
401 authentication_required No credential at all
403 not_an_api_path A valid token, on a path that doesn't take tokens
403 plan_required The token's account isn't on a paid plan
403 insufficient_scope A read token, and the request writes
403 browser_only A path that answers a signed-in browser only: a Word file's preview and the live event streams

Start here: GET /api/v1/me/

Who the token belongs to, how the request was authenticated, and every shelf the account belongs to with its roles (owner, organizer, reviewer, submitter, member).

{
  "user": {"id": 7, "email": "you@example.org", "name": "Ada Reader"},
  "auth": {"kind": "token", "name": "my script", "scopes": ["read"]},
  "workspaces": [
    {
      "slug": "spring-2026-playwriting",
      "name": "Spring 2026 Playwriting Prize",
      "workspace_type": "literary_contest",
      "roles": ["reviewer", "member"]
    }
  ]
}

The annotation endpoints under /notate/api/ take a token as they take a signed-in session. Everything else, the review queue and writing a review among them, is still the web pages only.

A token is what an AI assistant holds, so it follows the shelf's rule for readers' own assistants. Where that rule allows yours none, on the work as it arrived or for your role, the annotation list, an update's reply and the export answer with the highlights and comments but without the work's own words: selected_text is null, the selector loses its exact, prefix and suffix, the export has no quotes, and a list says "words_withheld": true. Work keeps the rule it arrived under: a shelf can tighten its rule at any time, and loosening it reaches only work sent afterwards. On a shelf of submitted work the rule covers the organizers' assistants only; on a shelf of its members' own documents, any member's.

The files the web and the Mac app exchange are specified under file formats.