API

4 min read Original article ↗

developers

Build on textlog

The public API is a small way to build feeds, profile cards, post embeds, and live widgets. Reading needs no account or API key. Writing is available to every account with a bearer token.

Base URL

https://textlog.cc/api/v1

All API endpoints allow cross-origin requests. The machine-readable specification is at /api/openapi.json.

Endpoints

POST/auth/request
Email a sign-in code to an existing account.

POST/auth/verify
Exchange the code for a session token.

DELETE/auth/session
Sign out by revoking the token you are using.

GET/me
Get the signed-in account.

PATCH/me
Update your bio.

POST/posts
Create a post, or reply by including parent_id.

GET/posts/:id
Get a single public post.

PATCH/posts/:id
Edit a post you own.

DELETE/posts/:id
Delete a post you own. Replies remain and the post becomes a “(deleted)” tombstone.

GET/posts/:id/replies
Get the latest direct replies.

POST/posts/:id/report
Report a post.

GET/users/:handle
Get a public profile and its counts.

GET/users/:handle/posts
Get a user's latest posts and replies.

POST/users/:handle/follow
Follow a user.

DELETE/users/:handle/follow
Unfollow a user.

POST/users/:handle/block
Block a user.

DELETE/users/:handle/block
Unblock a user.

GET/feeds/latest
Get the latest public posts and replies.

GET/feeds/hot
Get posts ranked by recent activity and replies.

GET/tags/:tag/posts
Get the latest posts carrying a hashtag.

GET/search?q=:query
Search public posts by text.

GET/firehose
Stream new posts as server-sent events.

RSS and Atom

Feed collections are also available as RSS 2.0 or Atom 1.0. Add .rss or .atom to the collection address and enter it manually in a feed reader.

/feeds/latest.rss
/feeds/hot.atom
/users/:handle/posts.rss
/tags/:tag/posts.atom

Public data archive

Download the latest daily, read-only snapshot as dump.zip. It contains paginated JSON files for public handles and bios, posts and reply links, mentions, hashtags, and follow relationships. The accounts are frozen: the archive contains no login credentials, contact details, record timestamps, blocks, reports, deleted content, or other private data.

curl -O https://textlog.cc/dump.zip

Embeds

Add a read-only textlog card to any website with an iframe. Copy an example and replace the handle, hashtag, or post number. Feed embeds show the five newest notes and all links open textlog. See every format together on the live embed examples page.

<iframe
  src="https://textlog.cc/embed/user/alice?theme=system&accent=sage&font=menlo"
  title="@alice on textlog"
  width="100%" height="520" loading="lazy"
  style="border:0"
></iframe>
<!-- latest notes -->
<iframe src="https://textlog.cc/embed/latest?theme=dark&accent=purple"
  title="Latest notes on textlog" width="100%" height="520" style="border:0"></iframe>

<!-- hot notes -->
<iframe src="https://textlog.cc/embed/hot?theme=light&accent=blue"
  title="Hot notes on textlog" width="100%" height="520" style="border:0"></iframe>

<!-- a hashtag -->
<iframe src="https://textlog.cc/embed/tag/photography?theme=system&accent=theme"
  title="#photography on textlog" width="100%" height="520" style="border:0"></iframe>

<!-- one post -->
<iframe src="https://textlog.cc/embed/post/123?theme=sepia&accent=rust"
  title="Post 123 on textlog" width="100%" height="220" style="border:0"></iframe>

Appearance uses the theme, accent, and font query parameters.

Themes: system, light, dark, sepia, and dracula.

Accents: theme, sage, purple, cyan, pink, amber, blue, and rust.

Fonts: system, sf, menlo, monaco, consolas, cascadia, courier, lucida, dejavu, liberation, ubuntu, noto, droid, source, roboto, fira, jetbrains, and hack.

Pagination

Collections accept limit from 1–100 (default 20). Pass the opaque pagination.next_cursor value back as cursor to fetch the next page.

curl 'https://textlog.cc/api/v1/feeds/latest?limit=10'

Search

Search is public and uses the same prefix matching as the website. Separate words must all match.

curl 'https://textlog.cc/api/v1/search?q=quiet+notes&limit=10'

Firehose

The firehose is live-only and includes top-level posts and replies. Each new post arrives as a post event. Reconnects begin from that moment and do not replay missed events.

const events = new EventSource('https://textlog.cc/api/v1/firehose')
events.addEventListener('post', event => {
  const post = JSON.parse(event.data)
})

Writing

Every account can use the write endpoints. Authenticate with a bearer token; no separate API access setting is required.

Sign in with the code emailed alongside your magic link. Accounts are only created in a browser, so the API cannot sign anyone up.

curl -X POST https://textlog.cc/api/v1/auth/request \
  -H 'content-type: application/json' -d '{"email":"you@example.com"}'

curl -X POST https://textlog.cc/api/v1/auth/verify \
  -H 'content-type: application/json' -d '{"email":"you@example.com","code":"123456"}'

The returned token is an ordinary session. It is listed under account security and can be revoked there. Send it as a bearer token. Cookies are never accepted for writes.

curl -X POST https://textlog.cc/api/v1/posts \
  -H "authorization: Bearer $TOKEN" \
  -H 'content-type: application/json' -d '{"body":"hello from an app"}'

Limits and errors

API reads are limited to 120 requests per minute per IP. Firehose clients may hold three simultaneous connections per IP. Writes are limited to 60 per hour per account, and posting keeps the same limit as the website: three posts every five minutes. A limited response uses 429 and includes Retry-After.

{
  "error": { "code": "not_found", "message": "Post not found" }
}