API
The Thoughtful REST API lets you read and write to your workspace from any application, script, or AI agent.
Overview
The Thoughtful API gives you programmatic access to your workspace. Everything you can do in the CLI or web app, you can do via the API: create and edit pages, search your knowledge base, manage threads, and more.
The API is RESTful, uses JSON for request and response bodies, and authenticates via Bearer tokens.
Base URL:
Authentication
There are two ways to authenticate: API keys (recommended for scripts and integrations) and email-based tokens (used by the CLI and mobile app).
API Keys
The simplest way to authenticate. Create an API key in Settings > API Keys in the web app.
Each key is scoped to a specific workspace. Include it in the Authorization header:
API keys don't expire, but can be revoked at any time from Settings.
Email-based tokens
The CLI and mobile app use an email verification flow. This is useful if you need to authenticate on behalf of a user rather than a workspace.
Note: email-based auth endpoints use a different base URL: https://www.thoughtful.app/api/auth/mobile
Step 1: Request a verification code.
A 6-digit code is sent to the email address. The code expires after 10 minutes.
Step 2: Exchange the code for tokens.
Response:
Access tokens expire. Use the refresh token to get a new pair:
Common Patterns
Response format
Successful responses return the resource directly:
List endpoints return an array under a pluralized key:
Errors
Errors return an error field with an HTTP status code:
| Status | Meaning |
|---|---|
400 | Bad request — missing or invalid parameters |
401 | Unauthorized — invalid or expired token |
404 | Not found — resource doesn't exist in this workspace |
409 | Conflict — content was modified (optimistic concurrency) |
500 | Server error |
Pagination
Some list endpoints accept limit and offset parameters:
Responses include a totalPages field so you can calculate remaining pages:
Content hashing
The API uses content hashes for optimistic concurrency control on page content. When you read a page's content, the response includes a contentHash. Pass it back on writes — if the content changed between your read and write, the API returns 409 Conflict instead of silently overwriting.
Pages
Pages are the core data type — structured documents for storing knowledge, notes, specs, and anything else.
Page object
Status values: idea, not_started, on_track, at_risk, off_track, completed, paused
Type values: page (default), database, file
Icon object: { "type": "emoji" | "lucide", "value": "🎯" } or null
List pages
Returns all pages in the workspace as a flat list. Pages are organized in a tree via parentId.
Query parameters:
| Param | Type | Description |
|---|---|---|
compact | boolean | Return a compact text format optimized for AI consumption |
limit | number | Max number of pages to return |
offset | number | Number of pages to skip (use with limit for pagination) |
Response:
Get a page
Returns a single page by its slug, including its markdown content.
Response:
Create a page
Only title is required. All other fields are optional. The slug is auto-generated from the title.
Response:
Update a page
All fields are optional. Only provided fields are changed. Set parentSlug to null to move a page to the root.
Delete a page
Returns { "success": true } on success.
Page Content
Page content is collaborative markdown managed separately from page metadata. This lets multiple users and agents edit simultaneously without conflicts.
Get content
Response:
Replace content
Pass contentHash from a previous read to enable optimistic concurrency. If the content changed since your read, you'll get a 409 Conflict.
Append to content
Find and replace
Response:
Search within a page
Response:
Page Discovery
Search pages
Full-text search across page titles and content.
Query parameters:
| Param | Type | Description |
|---|---|---|
q | string | Search query (required) |
limit | number | Max results (default 20, max 100) |
Find similar pages
Returns pages semantically similar to the given page, using vector similarity.
Query parameters:
| Param | Type | Description |
|---|---|---|
limit | number | Max results (default 5) |
Get page outline
Returns the heading structure of a page — useful for navigating large documents.
Query pages
Filter pages by properties.
Query parameters:
| Param | Type | Description |
|---|---|---|
status | string | Comma-separated statuses (e.g. on_track,at_risk) |
owner | string | Filter by owner email |
type | string | Page type: page, database, file |
parent | string | Parent page slug |
blocked-by | string | Filter pages blocked by a specific page slug |
text | string | Filter by title/slug text match |
compact | boolean | Return compact text format optimized for AI consumption |
Response:
Note: the query endpoint returns totalCount (not totalPages).
Page history
Returns a timeline of recent page changes across the workspace.
Query parameters:
| Param | Type | Description |
|---|---|---|
since | string | ISO 8601 date — only show changes after this date |
limit | number | Max results |
page | string | Filter history to a specific page slug |
Batch Operations
Perform multiple page operations in a single request. Useful for bulk imports, migrations, or scripted workflows.
When dryRun is true, the request validates all actions and reports what would happen without making changes.
Response:
Search
Search across your entire workspace — pages, updates, milestones, and principles.
Query parameters:
| Param | Type | Description |
|---|---|---|
q | string | Search query (required) |
type | string | Filter by type: page, update, milestone, principle, or all (default) |
limit | number | Max results (default 20, max 100) |
Uses hybrid search (semantic + keyword) for best results. Returns scored matches:
Threads
Threads are AI chat conversations. You can create threads, send messages, and optionally get AI responses.
Thread object
List threads
Returns recent threads, newest first.
Create a thread
The message field is optional. If provided, it becomes the first message in the thread and the thread title is derived from it.
Response:
Get a thread
Returns a single thread by its ID.
Get thread messages
Returns all messages in a thread.
Query parameters:
| Param | Type | Description |
|---|---|---|
raw | boolean | Return messages in raw format (default false) |
Send a message
Send a message and get AI response
This sends the message and waits for the AI to generate a response. The response includes both the user message and the AI reply.
Rate Limits
Public API endpoints are rate limited per API key (or per user for token-based auth):
| Tier | Requests per minute |
|---|---|
| Standard | 60 |
| Batch operations | 10 |
| Search | 30 |
Rate-limited responses return 429 Too Many Requests with a Retry-After header.
Rate limit headers are included on every response:
Examples
Create a page and add content
Search and read
AI conversation
Python
CLI
The Thoughtful CLI wraps this API in a convenient command-line interface. Install with bun add -g thoughtful.