InterlinedList exposes an HTTP API that lets you build integrations, native clients, scripts, and automations on top of the platform. All request and response bodies are JSON unless noted otherwise.
This page is an index. Pick the section you need from the sidebar (or the list below) for full request/response details.
Interactive explorer: Try endpoints live in the browser with the Swagger / OpenAPI explorer at
/api-docs. Authorize with a sync token and send real requests. The raw machine-readable spec is served at/api/openapi.json.
Paths are relative to the InterlinedList deployment you are targeting:
https://interlinedlist.com
For example: https://interlinedlist.com/api/messages
Two methods are supported. See Authentication & OAuth for details.
POST /api/auth/login; used by the web app and any browser client on the same origin.POST /api/auth/sync-token; used by native, mobile, and CLI clients. Send as Authorization: Bearer <token>.Endpoints documented as Session or Bearer accept either. Endpoints documented as Session only require the cookie.
Which one an endpoint uses is documented per operation in the OpenAPI spec and shown in the explorer. You cannot guess it from the URL:
| Envelope | Looks like | Used by |
|---|---|---|
{ message, data } | { "message": "List created successfully", "data": { … } } | The Lists family — lists, rows, schema |
{ <entity> } | { "document": { … } }, { "user": { … } }, { "views": [ … ] } | Documents, saved views, the current user, DM sends |
| Bare object | { "id": "msg_1", "content": "…" } | Single-message reads, app settings, DM pages, notification feeds |
Every date is an ISO-8601 UTC string, so a single global date strategy decodes the whole API. A column that is optional in the database is nullable on the wire and is typed ["string", "null"] (or similar) in the spec — a strict decoder such as Swift Codable or kotlinx will not trip on it.
Errors always return JSON with an error field:
{ "error": "Not authenticated" }
Common status codes: 400 bad request, 401 not authenticated, 403 forbidden (e.g. email not verified, subscriber feature), 404 not found, 409 conflict, 413 payload too large, 429 rate limited, 500 server error.
Many error responses also include a machine-readable code alongside the human-readable error string, so clients can switch on the reason without parsing prose:
{ "error": "Your account is restricted and is currently read-only.", "code": "account_restricted" }
Accounts have a status lifecycle (probation, active, restricted, suspended, banned) that can limit or block write actions. When it does, the response carries one of these codes. These codes are only returned when the server has account-status enforcement enabled; on a server where it is off, none of them appear.
| Status | Code | HTTP | Meaning |
|---|---|---|---|
| 403 | account_banned | Forbidden | The account is banned. (Banned accounts are also logged out, so this is rare in practice.) |
| 403 | account_suspended | Forbidden | The account is suspended and is read-only. Reads still work; all writes are blocked. |
| 403 | account_restricted | Forbidden | The account is restricted and is read-only. Reads still work; all writes are blocked. |
| 403 | account_probation_feature | Forbidden | The account is new (probation) and tried a feature reserved for verified accounts: direct messages, media upload, cross-posting, scheduled posts, or creating a list / document / organization. |
| 429 | account_probation_rate_limited | Too Many Requests | A probation account exceeded its posting rate limit (3 per rolling hour, 10 per rolling 24 hours). The response includes a Retry-After header and a scope of "hour" or "day". |
Read (GET) endpoints are never blocked by account status.
Paginated lists include a pagination object alongside the data array:
{
"data": [ ... ],
"pagination": {
"total": 84,
"limit": 20,
"offset": 0,
"hasMore": true
}
}
Use limit and offset (or page) as query parameters to page through results.
Some features require an active paid subscription. Check GET /api/user for the customerStatus field:
| Value | Meaning |
|---|---|
"free" | No subscription |
"subscriber" | Active subscriber (legacy) |
"subscriber:monthly" | Active monthly subscriber |
"subscriber:annual" | Active annual subscriber |
Any non-"free" status grants subscriber access. Features gated behind a subscription include image and video attachments on messages, scheduled posts, cross-posting to Mastodon/Bluesky/LinkedIn/X (Twitter), and document creation. Sending a subscriber-only field as a free user returns 403 Forbidden:
{ "error": "This feature requires an active subscription." }
POST /api/auth/sync-token
Content-Type: application/json
{ "email": "you@example.com", "password": "yourpassword" }
Then:
GET /api/user
Authorization: Bearer 3f1c9e...<64 hex chars>...a8
POST /api/messages
Authorization: Bearer 3f1c9e...<64 hex chars>...a8
Content-Type: application/json
{ "content": "Hello from the API!", "publiclyVisible": true }
See Messages for the full message body reference.
| Section | What's covered |
|---|---|
| Authentication & OAuth | Login, register, sync tokens, password reset, OAuth providers, account linking, logout, multi-account |
| Users and Profile | Current user, profile updates, avatars, linked identities, email change, account deletion |
| Public Profiles | No-auth endpoints for viewing public user content |
| Messages | Posting, replies, dig reactions, scheduled posts, media uploads, cross-posting |
| Direct Messages | Private one-to-one messaging between mutual followers: send, folders, threads, read state, image attachments |
| Lists | List CRUD, schema (DSL object), data rows, watchers, connections, search |
| List Schema DSL | Full reference for the schema object: column types, the required-column rule, validation rules, conditional visibility |
| List Folders | Top-level folder hierarchy for organising lists |
| Documents | Document CRUD, delta sync, templates, search, image uploads |
| Document Folders | Folder hierarchy for organising documents |
| Create from… (Materialize) | Turn messages, lists, rows, or documents into a new list, document, or both |
| Sharing & Share Links | Tokenized share links and per-person roles for documents and lists |
| Application Settings & Devices | Per-user, per-app synced settings (account + per-device), device registry, and first-run bootstrap |
| Following | Follow/unfollow, follow requests, follower & following lists |
| Moderation | Block and mute users, report messages and users |
| Organizations | Org CRUD, members, LinkedIn page integration |
| Notifications | Notification tray, mark read, single & bulk operations |
| Push Notifications | Register and unregister device tokens |
| Exports | CSV exports of messages, lists, list rows, and follows |
| GitHub Integration | Connected-account GitHub issue and repo helpers |
| LinkedIn Integration | Personal LinkedIn posting targets |
| AI Integration | Suggest/generate AI features (lists, documents, series, writing assist). Subscriber only; powered by the site's own Anthropic key |
| Utility Endpoints | Image proxy, geolocation, weather, tag discovery, blog subscription, OAuth client metadata, status probes |
| Administration | Admin-only user and email log management |
These per-category pages are the canonical human reference for the InterlinedList HTTP API. For the machine-readable contract and a live "try it" console, use:
npx openapi-typescript) types responses rather than falling back to any.