ThreadPage
Créer un fil
Toute la documentation

Cette référence est en anglais.

Script or API

Script or API gives your own script, server or workflow a token and the access the owner chooses. Pick what to build below, then add your first note step by step.

Afficher en Markdown

Sur cette page
  1. Choose what to build
  2. Quickstart
  3. Test without touching your notes
  4. What to read next
  5. Machine-readable

Choose what to build

Choose what to build
I want to…UseRead
add notes from a scriptthe Integration APINotes
post a service’s events into a threadan endpoint URLEndpoint URLs
react when notes changea webhook or a pull feedReceive webhooks, Pull feed
answer notes addressed to my workerRequestsRequests
let an assistant work in my notesthe MCP serverMCP server

Quickstart

You will check a token, find a thread, add a note and read its receipt. Each step shows curl, JavaScript and Python. curl examples are for bash; on Windows use WSL or Git Bash.

Step 0: Check your plan

With Free, a connection can only add notes to your Inbox: use POST /inbox/notes. Writing to a thread answers 403 pro_required. Apart from GET /connection and GET /operations/{operation_id}, everything else on these pages needs Pro with Sync turned on.

Step 1: Create a connection

In ThreadPage, open Settings → Connections, go to Automations and choose Connect an automation → Script or API. Enter a Name, choose what it can do and which threads and folders it can use, then choose Connect. Choose Copy token and keep it in a secret store: it is shown once.

For this quickstart, Add only with one selected thread is enough. On Free, the connection has Add to Inbox. Access levels explains each level.

Step 2: Check the token

Put the token in an environment variable, then ask the API which connection it belongs to. The JavaScript and Python steps use the call helper of the whole flow.

Shell
export THREADPAGE_TOKEN=tp_your_token
API=https://thread.page/api/integrations/v1
curl -sS -m 30 "$API/connection" \
  -H "Authorization: Bearer $THREADPAGE_TOKEN" | tee connection.json | jq .

The answer says what the token may do and when it stops working:

JSON
{
  "id": "6b1d0f4e-2c8a-4e57-9a3b-1f0c7d2e5a94",
  "name": "Release bot",
  "level": "append",
  "can": "Add notes to threads you choose and see those threads’ titles.",
  "cannot": "Can’t read notes.",
  "access": {
    "version": 3,
    "level": "append",
    "scope": "selected",
    "folder_ids": [],
    "thread_ids": ["0e7c4b2a-91d3-4f6e-8a25-3c1b9d7f4e60"],
    "excluded_folder_ids": [],
    "excluded_thread_ids": []
  },
  "permissions": {
    "read": false,
    "create_notes": true,
    "add_to_inbox": true,
    "edit_notes": "none",
    "organize": false
  },
  "manage_url": "https://thread.page/app/settings/connections/6b1d0f4e-2c8a-4e57-9a3b-1f0c7d2e5a94?access=read_add",
  "shared_places": [],
  "expires_at": "2027-01-29T09:30:00Z"
}

If permissions.create_notes is false and permissions.add_to_inbox is true, this connection adds notes only to the Inbox: skip to step 4 and use POST /inbox/notes.

Step 3: Find a thread

List the threads the connection can see, or copy the ID from the thread’s address in your browser: the part after threads/. The examples use the only thread the connection sees, and otherwise ask you to set THREAD_ID.

curl -sS -m 30 "$API/threads?limit=50" \
  -H "Authorization: Bearer $THREADPAGE_TOKEN" | tee threads.json | jq -r '.items[] | "\(.id)  \(.title)"'

Step 4: Add a note

Create one Operation-Id before the request and send the same one on every retry. A retry with the same ID returns the same receipt instead of a second note.

With Pro and Sync, add the note to the thread:

OP=$(uuidgen)
curl -sS -m 30 --retry 3 --retry-all-errors "$API/threads/$THREAD_ID/notes" \
  -H "Authorization: Bearer $THREADPAGE_TOKEN" \
  -H "Operation-Id: $OP" \
  -H "Content-Type: application/json" \
  -d '{"content": {"markdown": "**Build 412** passed.\n\nDeployed to staging."}}' | jq .
JSON
{
  "operation_id": "8a6e0804-2bd0-4672-b79d-d97027f9071a",
  "status": "accepted",
  "note_id": "4c2f8e19-7a6b-4d3e-b1c0-95e8f2a7d364",
  "revision": 1,
  "accepted_at": "2026-10-31T09:30:00Z",
  "url": "https://thread.page/app/notes/4c2f8e19-7a6b-4d3e-b1c0-95e8f2a7d364"
}

With Free, add it to the Inbox:

OP=$(uuidgen)
curl -sS -m 30 --retry 3 --retry-all-errors "$API/inbox/notes" \
  -H "Authorization: Bearer $THREADPAGE_TOKEN" \
  -H "Operation-Id: $OP" \
  -H "Content-Type: application/json" \
  -d '{"content": {"text": "Build 412 passed."}}' | jq .
JSON
{
  "operation_id": "3f2c1d0e-9b8a-4c7d-8e6f-5a4b3c2d1e0f",
  "status": "accepted",
  "note_id": "a91e5c37-2b4d-4f80-9c6e-7d3a1b0f5e28",
  "delivery": "inbox",
  "accepted_at": "2026-10-31T09:30:00Z",
  "url": null
}

"delivery": "inbox" means the note waits for the browser that collects your Inbox, and it appears there when ThreadPage is open. With Pro and Sync the receipt says "account" and has the note’s url.

Step 5: Read the receipt

If the answer to step 4 got lost, read the receipt instead of writing again:

curl -sS -m 30 "$API/operations/$OP" \
  -H "Authorization: Bearer $THREADPAGE_TOKEN" | jq .

It answers the receipt from step 4. A 404 unavailable means the write never reached ThreadPage: send it again with the same Operation-Id.

The whole flow

#!/usr/bin/env bash
# ThreadPage Quickstart: check the token, find a thread, add a note, read its receipt.
# Needs bash, curl 7.71 or newer, uuidgen and jq. Run: THREADPAGE_TOKEN=tp_… bash quickstart.sh
# Each step prints ThreadPage's answer, an error's JSON with its code included; it keeps
# connection.json and threads.json in the current folder.
# Set THREAD_ID when the connection sees more than one thread.
set -euo pipefail
API=https://thread.page/api/integrations/v1

curl -sS -m 30 "$API/connection" \
  -H "Authorization: Bearer $THREADPAGE_TOKEN" | tee connection.json | jq .

if [ "$(jq -r '.permissions.create_notes' connection.json)" = "true" ]; then
  curl -sS -m 30 "$API/threads?limit=50" \
    -H "Authorization: Bearer $THREADPAGE_TOKEN" | tee threads.json | jq -r '.items[] | "\(.id)  \(.title)"'
  if [ -z "${THREAD_ID:-}" ]; then
    if [ "$(jq '.items | length' threads.json)" != 1 ]; then
      echo "Set THREAD_ID to one of the threads above." >&2
      exit 1
    fi
    THREAD_ID=$(jq -r '.items[0].id' threads.json)
  fi

  OP=$(uuidgen)
  curl -sS -m 30 --retry 3 --retry-all-errors "$API/threads/$THREAD_ID/notes" \
    -H "Authorization: Bearer $THREADPAGE_TOKEN" \
    -H "Operation-Id: $OP" \
    -H "Content-Type: application/json" \
    -d '{"content": {"markdown": "**Build 412** passed.\n\nDeployed to staging."}}' | jq .
else
  OP=$(uuidgen)
  curl -sS -m 30 --retry 3 --retry-all-errors "$API/inbox/notes" \
    -H "Authorization: Bearer $THREADPAGE_TOKEN" \
    -H "Operation-Id: $OP" \
    -H "Content-Type: application/json" \
    -d '{"content": {"text": "Build 412 passed."}}' | jq .
fi

curl -sS -m 30 "$API/operations/$OP" \
  -H "Authorization: Bearer $THREADPAGE_TOKEN" | jq .

If it fails

Errors
CodeHTTPWhenWhat to doRetryable
authentication_required401No token was sent.Send Authorization: Bearer tp_….No
invalid_token401The token is wrong, revoked or replaced, or it was retired: the owner changed their password, or reset or restored the workspace. /mcp also answers it for a token that only answers its connection's requests.Ask the owner for a new token.No
token_expired401, 409The token's term ended, or it went 90 days without a call: details.reason is term or inactivity, details.expired_at when. An endpoint URL answers 409 with outcome blocked.Ask the owner to renew it in Settings → Connections; the same token then works again.No
pro_required403It needs Pro: on Free a connection adds notes only to the Inbox.Use POST /inbox/notes (MCP: create_note without thread_id), or tell the owner.No
cloud_required403It needs the owner's cloud copy: Pro without Sync.Tell the owner to turn on Sync; adding to the Inbox works meanwhile.No
read_not_allowed403Reading, or subscribing to events, on Add only or Add to Inbox.Tell the person and give them details.manage_url.No
write_not_allowed403, 409Adding on Read only, adding to a thread on Add to Inbox, a new thread or a reminder on Add only, or receiving requests below Read and add (details.needs and details.manage_url; the message names the level); an assistant whose sign-in holds no write scope; a connection whose access leaves out the Inbox thread. An endpoint URL answers 409 with outcome blocked.Give the person details.manage_url where there is one; otherwise tell them.No
unavailable404Not found within this connection's scope.Don't guess other IDs; ask the person whether the item is in scope.No
quota_exhausted429Free's 3,000 connection notes this month are used.Stop until details.resets_at. There is no Retry-After.No
inbox_full4091,000 notes or 20 MB wait for the owner's browser to collect them.Ask the owner to open ThreadPage, then retry later with the same Operation-Id.No

Test without touching your notes

  • Create a separate connection that reaches one test thread or folder instead of All threads.
  • GET /events/sample shows the shape of real events. A Test event reaches your Note updates URL signed like any event, with data.test set to true. Test request on a script that receives requests, or Send test on a Send notes you @ to a URL connection, sends a request without a note.
  • Undo changes… in the connection’s details undoes its changes, and can move what it added to Trash. Restore from Trash… brings back what it moved to Trash.
  • Choose Disconnect… when you are done.

Machine-readable

  • The contract: OpenAPI description.
  • Import the OpenAPI description into Postman, Bruno or Insomnia.
  • Generate a client from the OpenAPI description; there is no official SDK.
  • For agents: llms.txt. Every page here has a Markdown version at the same address with .md.