MCP, CLI and API
Connect your archive to Claude, Cursor, the terminal or your own code. All three use the same personal API keys and are included in both plans.
API keys
Make a key in mark under Settings → API, MCP and CLI. Give it a name you'll recognize, like “Claude on my laptop”, and copy it straight away: it's shown once. Keys start with mark_.
- Send the key on every request as a Bearer token. The MCP setups below do this for you.
- A key can read your whole archive and add to it. It can't delete anything or touch billing.
- Keys need an active plan, Starter or Growth. You can have up to 10, and revoke any of them in Settings.
Authorization: Bearer mark_YOUR_KEY
MCP server
With MCP, your assistant can search your archive, read whole posts and articles, quote your highlights, and save or file new links, all from the chat. The server lives at https://mark-it.app/api/mcp.
Claude Code
claude mcp add --transport http mark https://mark-it.app/api/mcp \ --header "Authorization: Bearer mark_YOUR_KEY"
Cursor
Add this to ~/.cursor/mcp.json, or to .cursor/mcp.json in a project.
{
"mcpServers": {
"mark": {
"url": "https://mark-it.app/api/mcp",
"headers": {
"Authorization": "Bearer mark_YOUR_KEY"
}
}
}
}Claude Desktop
Claude Desktop connects through mcp-remote, which needs Node. Add this to claude_desktop_config.json and restart the app.
{
"mcpServers": {
"mark": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://mark-it.app/api/mcp",
"--header",
"Authorization:${MARK_AUTH}"
],
"env": {
"MARK_AUTH": "Bearer mark_YOUR_KEY"
}
}
}
}Claude.ai and ChatGPT connectors need OAuth sign-in, which mark doesn't support yet. Any client that can send a header works today.
Tools
| Tool | What it does |
|---|---|
search_saves | Full-text search across titles, authors and text. Optional folder, kind and limit. |
list_saves | Recent saves, filtered by folder, kind or unread, and paged with a cursor. |
get_save | One save in full: text, quoted post, media, your note and highlights. |
list_folders | Your folders with their paths and how many saves each holds. |
save_url | Archive a link, optionally straight into a folder. |
move_save | File a save into a folder, or take it out of one. |
The first four only read. The server speaks Streamable HTTP, is stateless and answers with plain JSON (no SSE stream or session id).
CLI
mark brings your archive to the terminal: save a link, search, and read what you kept without leaving the shell. It's a single file with no dependencies and needs Node 20 or later.
Coming soon to npm. Until it's published, the MCP server and REST API above and below do everything the CLI does.
Log in
mark login # asks for your key without echoing it mark login --key mark_YOUR_KEY # or pass it in
The key is saved to ~/.config/mark/config.json, readable only by you (on Windows, %APPDATA%\mark\config.json). Set MARK_API_KEY to use a different key for one command or in CI.
Commands
mark whoami Account, plan and save count
mark save <url> [--folder <folder>] Archive a post, article or any web page
mark ls [--folder <f>] [--kind <k>] [--unread] [--limit <n>] [--cursor <c>]
mark search <words…> [--folder <f>] [--kind <k>] [--limit <n>]
mark show <id> Full text, quoted post, media, note and highlights
mark mv <id> <folder> File a save ("mark mv <id> --none" takes it out)
mark folders Folders with paths and counts
mark logout- A folder can be its id, its name or its full path, like
"Design / Pricing". - Kinds are
post,articleandlink. - Add
--jsonto any command for the raw API response, ready to pipe intojq. SetNO_COLOR=1to turn colors off.
REST API
Every endpoint lives under https://mark-it.app/api/v1, takes and returns JSON, and needs your key in the Authorization header.
| Endpoint | What it does |
|---|---|
| GET /me | Your account, plan and save count |
| GET /saves | List or search saves |
| POST /saves | Save a link |
| GET /saves/:id | One save in full |
| PATCH /saves/:id | Move a save to another folder |
| GET /folders | Your folders |
GET/api/v1/me
Who the key belongs to. saveLimit is 20 on Starter and null on Growth.
curl https://mark-it.app/api/v1/me \ -H "Authorization: Bearer mark_YOUR_KEY"
{
"email": "you@example.com",
"name": "Your Name",
"plan": "Starter",
"tier": "pro",
"saves": 12,
"saveLimit": 20
}GET/api/v1/saves
Your saves, newest first. Every query parameter is optional.
| Parameter | Description |
|---|---|
q | Search words. Each word matches as a prefix against titles, authors and text. |
folder | A folder id, name or full path. |
kind | Only post, article or link. |
unread | true for saves you haven't opened yet. |
limit | 1 to 50. Defaults to 20. |
cursor | The nextCursor from the previous page. |
curl "https://mark-it.app/api/v1/saves?q=pricing&limit=10" \ -H "Authorization: Bearer mark_YOUR_KEY"
{
"saves": [
{
"id": "3f2a9c1e-8b7d-4c1a-9e2f-5a6b7c8d9e0f",
"kind": "post",
"platform": "x",
"url": "https://x.com/lenanovak/status/1834000000000000000",
"appUrl": "https://mark-it.app/home/item/3f2a9c1e-8b7d-4c1a-9e2f-5a6b7c8d9e0f",
"title": null,
"author": {
"name": "Lena Novak",
"handle": "lenanovak"
},
"excerpt": "Show the price before the sign-up button. Hiding it costs you more trust than it saves.",
"postedAt": "2026-09-02T14:20:00Z",
"savedAt": "2026-09-03T08:05:12Z",
"isRead": true,
"sourceDeletedAt": "2026-09-10T08:12:00Z",
"folderId": "a1b2c3d4-0000-4000-8000-000000000001"
}
],
"nextCursor": null
}sourceDeletedAtis set once mark notices the original was deleted. Your copy stays readable.appUrlopens the archived copy in mark. It'snullfor links, which open their own page.nextCursorisnullon the last page.
POST/api/v1/saves
Archives a link: an X post or article, a LinkedIn or Reddit post, or any web page. folder is optional. Returns 201 for a new save, or 200 when you'd already saved it (the copy is refreshed).
curl -X POST https://mark-it.app/api/v1/saves \
-H "Authorization: Bearer mark_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://x.com/someone/status/123","folder":"Design"}'{
"save": { "id": "…", "kind": "post", … },
"created": true
}GET/api/v1/saves/:id
One save in full. On top of the list fields, it includes:
| Field | Description |
|---|---|
text | The full archived text. Markdown for articles, the post text for posts, the description for links. |
quoted | The quoted post, { unavailable: true } if it couldn't be fetched, or null. |
media | Images, videos and GIFs. archivedUrl is mark's copy, a link that works for one hour. |
note | Your note on the save, if any. |
highlights | Each with its quote, your comment and its color. |
curl https://mark-it.app/api/v1/saves/3f2a9c1e-8b7d-4c1a-9e2f-5a6b7c8d9e0f \ -H "Authorization: Bearer mark_YOUR_KEY"
PATCH/api/v1/saves/:id
Moves a save into a folder, or out of any folder with null. Returns the updated save.
curl -X PATCH https://mark-it.app/api/v1/saves/3f2a9c1e-8b7d-4c1a-9e2f-5a6b7c8d9e0f \
-H "Authorization: Bearer mark_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"folder":"Design / Pricing"}'GET/api/v1/folders
Every folder, with its full path and how many saves it holds.
curl https://mark-it.app/api/v1/folders \ -H "Authorization: Bearer mark_YOUR_KEY"
{
"folders": [
{
"id": "a1b2c3d4-0000-4000-8000-000000000001",
"name": "Pricing",
"path": "Design / Pricing",
"parentId": "a1b2c3d4-0000-4000-8000-000000000000",
"emoji": "💸",
"color": "green",
"count": 7
}
]
}Referring to folders
Wherever a request takes a folder, you can pass its id, its full path ("Design / Pricing") or just its name. Names are matched without regard to case. If two folders share a name, use the path or id instead; the API answers 409 folder_ambiguous.
Errors and limits
Errors come back with a status code and a JSON body you can branch on:
{
"error": {
"code": "not_found",
"message": "That isn't in your archive."
}
}| Status | Code | Meaning |
|---|---|---|
| 400 | validation | A parameter or the body is missing or malformed. |
| 401 | unauthenticated | The key is missing, mistyped or revoked. |
| 402 | subscription_required | The account has no active plan. |
| 403 | limit_reached | Starter's 20 saves are used up. |
| 404 | not_found | No such save or folder. |
| 409 | folder_ambiguous | Two folders share that name. Use the path or id. |
| 422 | invalid_url, not_available | The link isn't valid, or the post is private or deleted. |
| 429 | rate_limited | Too many requests. Wait for Retry-After seconds. |
| 502 | source_unreachable | The original site didn't answer. Try again shortly. |
| 500 | unknown | Something broke on mark's side. |
- 120 requests a minute per account, across every key.
- 30 saves a minute, the same as in the app.
- Starter holds 20 saves; Growth has no limit.
Stuck? Reach us at support@mark-it.app. No key yet? Pick a plan and make one in Settings.