# Get Current Account Source: https://docs.getmatter.com/api/account/get-me GET /v1/me Returns the authenticated user's account information and API quota. ## Response Always `"account"`. The account ID. Example: `act_k8x2m`. The user's display name. The user's email address. Rate limit quotas (requests per minute unless noted). All GET requests. POST, PATCH, DELETE requests. POST /items (each triggers extraction). GET requests with ?include=markdown. Per-second ceiling across all requests. ISO 8601 timestamp of account creation. ```bash cURL theme={null} curl https://api.getmatter.com/public/v1/me \ -H "Authorization: Bearer mat_your_token_here" ``` ```python Python theme={null} import requests response = requests.get( "https://api.getmatter.com/public/v1/me", headers={"Authorization": f"Bearer {token}"} ) account = response.json() ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.getmatter.com/public/v1/me", { headers: { Authorization: `Bearer ${token}` } }); const account = await response.json(); ``` ```json 200 theme={null} { "object": "account", "id": "act_k8x2m", "name": "Jane Smith", "email": "jane@example.com", "rate_limit": { "read": 120, "write": 30, "save": 10, "search": 30, "markdown": 20, "burst": 5 }, "created_at": "2024-06-15T10:30:00Z" } ``` # Delete Annotation Source: https://docs.getmatter.com/api/annotations/delete DELETE /v1/annotations/{id} Permanently delete an annotation. ## Path Parameters The annotation ID. Example: `ann_m2k8v`. ## Response Returns `204 No Content` on success. ```bash cURL theme={null} curl -X DELETE https://api.getmatter.com/public/v1/annotations/ann_m2k8v \ -H "Authorization: Bearer mat_your_token_here" ``` ```json 204 theme={null} (No content) ``` # Get Annotation Source: https://docs.getmatter.com/api/annotations/get GET /v1/annotations/{id} Returns a single annotation. ## Path Parameters The annotation ID. Example: `ann_m2k8v`. ## Response Always `"annotation"`. The annotation ID. The parent item ID. The highlighted text. User-added note, if any. ISO 8601 timestamp. ISO 8601 timestamp. ```bash cURL theme={null} curl https://api.getmatter.com/public/v1/annotations/ann_m2k8v \ -H "Authorization: Bearer mat_your_token_here" ``` ```json 200 theme={null} { "object": "annotation", "id": "ann_m2k8v", "item_id": "itm_r9f3a", "text": "The way to figure out what to work on is by working.", "note": "Core thesis of the essay", "created_at": "2026-03-30T18:32:00Z", "updated_at": "2026-03-30T18:32:00Z" } ``` # List Annotations Source: https://docs.getmatter.com/api/annotations/list GET /v1/items/{item_id}/annotations Returns all annotations for a specific item. ## Path Parameters The item ID. Example: `itm_r9f3a`. ## Query Parameters Number of annotations per page. Min 1, max 100. Cursor for the next page of results. ## Response Always `"list"`. Array of annotation objects. Always `"annotation"`. Annotation ID. The parent item ID. The highlighted text. User-added note, if any. ISO 8601 timestamp. ISO 8601 timestamp. Whether there are more results. Cursor for the next page. ```bash cURL theme={null} curl "https://api.getmatter.com/public/v1/items/itm_r9f3a/annotations" \ -H "Authorization: Bearer mat_your_token_here" ``` ```python Python theme={null} response = requests.get( "https://api.getmatter.com/public/v1/items/itm_r9f3a/annotations", headers={"Authorization": f"Bearer {token}"} ) annotations = response.json() ``` ```json 200 theme={null} { "object": "list", "results": [ { "object": "annotation", "id": "ann_m2k8v", "item_id": "itm_r9f3a", "text": "The way to figure out what to work on is by working.", "note": "Core thesis of the essay", "created_at": "2026-03-30T18:32:00Z", "updated_at": "2026-03-30T18:32:00Z" } ], "has_more": false, "next_cursor": null } ``` # Update Annotation Source: https://docs.getmatter.com/api/annotations/update PATCH /v1/annotations/{id} Set or remove the note on an annotation. ## Path Parameters The annotation ID. Example: `ann_m2k8v`. ## Body Parameters The note text. Pass `null` to remove the note. ## Response Returns the updated annotation. ```bash cURL theme={null} curl -X PATCH https://api.getmatter.com/public/v1/annotations/ann_m2k8v \ -H "Authorization: Bearer mat_your_token_here" \ -H "Content-Type: application/json" \ -d '{"note": "Core thesis of the essay"}' ``` ```json 200 theme={null} { "object": "annotation", "id": "ann_m2k8v", "item_id": "itm_r9f3a", "text": "The way to figure out what to work on is by working.", "note": "Core thesis of the essay", "created_at": "2026-03-30T18:32:00Z", "updated_at": "2026-03-30T20:45:00Z" } ``` # Authentication Source: https://docs.getmatter.com/api/authentication Authenticate with the Matter API using personal access tokens. Every request to the Matter API must include a valid API token. Tokens are scoped to your account and give full read/write access to your library. ## Getting your token 1. Open [Matter settings](https://web.getmatter.com/settings) 2. Click **Generate API Token** 3. Copy the token Your token looks like this: ``` mat_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8 ``` The `mat_` prefix identifies it as a Matter API token. If you ever see one in logs or code, you know what it is. ## Using your token Pass the token in the `Authorization` header on every request: ```bash theme={null} curl https://api.getmatter.com/public/v1/me \ -H "Authorization: Bearer mat_your_token_here" ``` **Never share your token or commit it to source control.** Treat it like a password. Use environment variables or a secrets manager. ## Token lifecycle | Action | What happens | | -------------- | --------------------------------------------------------------- | | **Generate** | Creates a new token. Any previous token is immediately revoked. | | **Regenerate** | Invalidates the old token and issues a new one. | | **Revoke** | Destroys the token. API access stops immediately. | You can have **one active token** at a time. Generating a new token automatically revokes the previous one. ## Security best practices ```bash theme={null} export MATTER_API_TOKEN="mat_your_token_here" curl https://api.getmatter.com/public/v1/me \ -H "Authorization: Bearer $MATTER_API_TOKEN" ``` ```bash theme={null} # .env (add to .gitignore!) MATTER_API_TOKEN=mat_your_token_here ``` If you suspect a token has been exposed, regenerate it immediately in your [settings](https://web.getmatter.com/settings). ## Error responses If authentication fails, the API returns `401 Unauthorized`: ```json theme={null} { "error": { "code": "unauthorized", "message": "Invalid or expired API token." } } ``` If your account doesn't have an active Pro subscription: ```json theme={null} { "error": { "code": "forbidden", "message": "The Matter API requires an active Pro subscription." } } ``` # Errors Source: https://docs.getmatter.com/api/errors How the Matter API communicates errors. The API uses standard HTTP status codes and returns structured JSON error bodies. ## Error format Every error response has this shape: ```json theme={null} { "error": { "code": "not_found", "message": "No item found with ID itm_abc123.", "field": null } } ``` | Field | Type | Description | | --------- | -------------- | --------------------------------------------------------- | | `code` | string | Machine-readable error code for programmatic handling. | | `message` | string | Human-readable description of what went wrong. | | `field` | string \| null | The request field that caused the error, when applicable. | ## HTTP status codes | Status | Meaning | When you'll see it | | ------ | --------------------- | ----------------------------------------------------------------------- | | `200` | OK | Successful read or update. | | `201` | Created | Successfully created a new resource. | | `204` | No Content | Successful delete. | | `400` | Bad Request | Invalid request body, missing required field, or malformed parameter. | | `401` | Unauthorized | Missing or invalid API token. | | `403` | Forbidden | Valid token but insufficient permissions (e.g., no Pro subscription). | | `404` | Not Found | The requested resource doesn't exist or doesn't belong to your account. | | `409` | Conflict | Resource already exists (e.g., duplicate tag name). | | `422` | Unprocessable Entity | Request is well-formed but semantically invalid (e.g., invalid URL). | | `429` | Too Many Requests | Rate limit exceeded. See [rate limits](/api/rate-limits). | | `500` | Internal Server Error | Something went wrong on our end. Retry with backoff. | ## Error codes | Code | Status | Description | | ------------------ | ------ | ------------------------------------------------------ | | `bad_request` | 400 | Generic invalid request. | | `validation_error` | 400 | A specific field failed validation. Check `field`. | | `unauthorized` | 401 | Invalid or missing API token. | | `forbidden` | 403 | Pro subscription required, or resource not accessible. | | `not_found` | 404 | Resource not found or not owned by you. | | `conflict` | 409 | Resource already exists. | | `unprocessable` | 422 | Request is syntactically valid but can't be processed. | | `rate_limited` | 429 | Too many requests. Check `Retry-After` header. | | `internal_error` | 500 | Server error. Retry with exponential backoff. | ## Validation errors When a specific field is invalid, the `field` property tells you which one: ```json theme={null} { "error": { "code": "validation_error", "message": "URL must start with http:// or https://.", "field": "url" } } ``` ## Handling errors ```python theme={null} response = requests.post(url, headers=headers, json=data) if response.status_code >= 400: error = response.json()["error"] if error["code"] == "rate_limited": retry_after = int(response.headers["Retry-After"]) time.sleep(retry_after) elif error["code"] == "validation_error": print(f"Fix field '{error['field']}': {error['message']}") else: print(f"Error: {error['message']}") ``` # IDs & Object Types Source: https://docs.getmatter.com/api/ids How resources are identified in the Matter API. Every resource in the API has a prefixed string ID and an `object` field that tells you its type. ## ID format IDs are opaque strings with a type prefix: | Resource | Prefix | Example | | --------------- | ------ | ----------- | | Account | `act_` | `act_k8x2m` | | Item | `itm_` | `itm_r9f3a` | | Annotation | `ann_` | `ann_m2k8v` | | Tag | `tag_` | `tag_n5j2x` | | Author | `aut_` | `aut_p4w7q` | | Reading Session | `rs_` | `rs_k8x2m` | The prefix tells you the resource type at a glance, which is helpful when debugging or reading logs. ## Object types Every response includes an `object` field identifying the resource type: ```json theme={null} { "object": "item", "id": "itm_r9f3a", "title": "How to Do Great Work" } ``` For lists: ```json theme={null} { "object": "list", "results": [ { "object": "item", "id": "itm_r9f3a" }, { "object": "item", "id": "itm_x7k2p" } ], "has_more": false, "next_cursor": null } ``` This makes it safe to handle polymorphic responses — you can always check `object` to know what you're looking at. ## Timestamps All timestamps are ISO 8601 strings in UTC: ``` 2026-03-30T18:30:00Z ``` Use these fields for sync, sorting, and display. See [incremental sync](/api/pagination#incremental-sync) for how to use `updated_at` to efficiently stay in sync. # Matter API Source: https://docs.getmatter.com/api/index REST API for saving articles, managing annotations, organizing tags, and syncing your Matter reading library. The Matter API gives you full read/write access to your library. Save articles, manage annotations, organize with tags, and sync your reading data with any tool you use. The API requires a Matter Pro subscription. [Upgrade to Pro](https://web.getmatter.com/settings) to get started. ## Base URL ``` https://api.getmatter.com/public/v1/ ``` ## Authentication All endpoints require a Bearer token in the `Authorization` header: ```bash theme={null} curl https://api.getmatter.com/public/v1/me \ -H "Authorization: Bearer mat_your_token_here" ``` See [Authentication](/api/authentication) for details on generating and managing tokens. ## Request format * All request bodies must be JSON with `Content-Type: application/json` * Query parameters are used for filtering and pagination * IDs in URLs are prefixed strings (e.g., `itm_r9f3a`) ## Response format All responses are JSON. Every object includes an `object` field identifying its type. **Single resource:** ```json theme={null} { "object": "item", "id": "itm_r9f3a", "title": "Example Article" } ``` **List of resources:** ```json theme={null} { "object": "list", "results": [...], "has_more": true, "next_cursor": "eyJpZCI6MTIzNH0=" } ``` **Error:** ```json theme={null} { "error": { "code": "not_found", "message": "No item found with ID itm_abc123." } } ``` ## Getting started Save your first article and retrieve your library in under 5 minutes. Generate and manage your API token. How resources are identified in the API. ## Concepts Cursor-based pagination and incremental sync. Request quotas and how to handle throttling. Error codes, status codes, and how to handle them. API versioning and compatibility guarantees. ## API Reference Articles, podcasts, videos, and everything in your library. Text highlights and notes you've made while reading. Labels you use to organize items in your library. Full-text search across your library. Your profile and API quota. # Save Item Source: https://docs.getmatter.com/api/items/create POST /v1/items Save a new item to your library by URL. Saving an item triggers content extraction in the background. The item is returned immediately, but metadata fields like `title`, `author`, and `word_count` may not be available until processing completes. Check the `processing_status` field to know when the item is ready: | Status | Meaning | | ------------ | -------------------------------------------------------------------------- | | `completed` | Content has been extracted. All fields are populated. | | `processing` | Extraction is in progress. Poll `GET /items/{id}` to check for completion. | | `failed` | Extraction failed (e.g., site is unreachable or unsupported). | About 40% of saves complete instantly (cached content). For the rest, processing typically takes 20-60 seconds. Save requests count against a separate [rate limit tier](/api/rate-limits) (10/min). ## Body Parameters The URL to save. Must be a valid `http://` or `https://` URL. Where to place the item. One of `queue` or `archive`. ## Response Returns the item with status `201`. If the URL is already in your library, the existing item is returned with status `200`. ```bash cURL theme={null} curl -X POST https://api.getmatter.com/public/v1/items \ -H "Authorization: Bearer mat_your_token_here" \ -H "Content-Type: application/json" \ -d '{"url": "https://paulgraham.com/greatwork.html", "status": "queue"}' ``` ```python Python theme={null} import requests import time # Save the item response = requests.post( "https://api.getmatter.com/public/v1/items", headers={ "Authorization": f"Bearer {token}", "Content-Type": "application/json" }, json={"url": "https://paulgraham.com/greatwork.html", "status": "queue"} ) item = response.json() # Poll until processing completes (if needed) while item["processing_status"] == "processing": time.sleep(5) item = requests.get( f"https://api.getmatter.com/public/v1/items/{item['id']}", headers={"Authorization": f"Bearer {token}"} ).json() print(item["title"]) # "How to Do Great Work" ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.getmatter.com/public/v1/items", { method: "POST", headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" }, body: JSON.stringify({ url: "https://paulgraham.com/greatwork.html", status: "queue" }) }); const item = await response.json(); ``` ```json "201 — completed (cached content)" theme={null} { "object": "item", "id": "itm_r9f3a", "title": "How to Do Great Work", "url": "https://paulgraham.com/greatwork.html", "site_name": "paulgraham.com", "author": { "object": "author", "id": "aut_p4w7q", "name": "Paul Graham" }, "status": "queue", "processing_status": "completed", "is_favorite": false, "content_type": "article", "word_count": 11842, "reading_progress": 0.0, "image_url": null, "tags": [], "updated_at": "2026-03-30T18:30:00Z" } ``` ```json "201 — processing (async extraction)" theme={null} { "object": "item", "id": "itm_r9f3a", "url": "https://paulgraham.com/greatwork.html", "status": "queue", "processing_status": "processing", "title": null, "author": null, "site_name": null, "content_type": null, "word_count": null, "is_favorite": false, "reading_progress": 0.0, "image_url": null, "tags": [], "updated_at": "2026-03-30T18:30:00Z" } ``` ```json 422 theme={null} { "error": { "code": "unprocessable", "message": "URL must start with http:// or https://.", "field": "url" } } ``` # Delete Item Source: https://docs.getmatter.com/api/items/delete DELETE /v1/items/{id} Permanently remove an item from your library. ## Path Parameters The item ID. Example: `itm_r9f3a`. ## Response Returns `204 No Content` on success. The item and all associated data (annotations, tags) are permanently removed. This action is irreversible. If you want to keep the item but move it out of your queue, update its status to `archive` instead. ```bash cURL theme={null} curl -X DELETE https://api.getmatter.com/public/v1/items/itm_r9f3a \ -H "Authorization: Bearer mat_your_token_here" ``` ```python Python theme={null} response = requests.delete( "https://api.getmatter.com/public/v1/items/itm_r9f3a", headers={"Authorization": f"Bearer {token}"} ) assert response.status_code == 204 ``` ```json 204 theme={null} (No content) ``` ```json 404 theme={null} { "error": { "code": "not_found", "message": "No item found with ID itm_r9f3a." } } ``` # Get Item Source: https://docs.getmatter.com/api/items/get GET /v1/items/{id} Returns a single item from your library with full metadata. ## Path Parameters The item ID. Example: `itm_r9f3a`. ## Query Parameters Comma-separated list of additional fields to include. Currently supported: `markdown`. When `markdown` is included, the response adds a `markdown` field with the parsed article body. These requests count against the [content rate limit](/api/rate-limits) (20/min). ## Response Always `"item"`. The item ID. The item's title. The original URL of the item. The source website name. The item's author, if known. Always `"author"`. Author ID. Author display name. One of `inbox`, `queue`, or `archive`. Content extraction status. One of `processing`, `completed`, or `failed`. See [Save Item](/api/items/create) for details. Whether the item is favorited. One of `article`, `video`, `podcast`, `pdf`, `tweet`, `newsletter`. Estimated word count. `null` for non-text content. Reading progress as a float from `0.0` to `1.0`. URL of the item's hero image, if available. The parsed article body as markdown. Only included when `?include=markdown` is set. `null` if the item hasn't been processed yet. Short excerpt or description of the item, if available. The item's position in the library (queue/archive). Non-null when the item has a library entry. Higher values are closer to the top. Use this to recreate library order locally. The item's 0-based index in the inbox feed. Non-null when the item is in the inbox. Lower values are closer to the top. Use this to recreate inbox order locally. Tags applied to this item. Always `"tag"`. Tag ID. Tag name. Number of items with this tag. ISO 8601 timestamp. ISO 8601 timestamp of the last change to this item or its associated data (status, reading progress, favorites, tags, annotations, or content re-extraction). For inbox items with no interactions, this is the time the item appeared in your inbox. ```bash cURL theme={null} curl https://api.getmatter.com/public/v1/items/itm_r9f3a \ -H "Authorization: Bearer mat_your_token_here" ``` ```bash "cURL (with markdown)" theme={null} curl "https://api.getmatter.com/public/v1/items/itm_r9f3a?include=markdown" \ -H "Authorization: Bearer mat_your_token_here" ``` ```python Python theme={null} response = requests.get( "https://api.getmatter.com/public/v1/items/itm_r9f3a", headers={"Authorization": f"Bearer {token}"}, params={"include": "markdown"} ) item = response.json() ``` ```json 200 theme={null} { "object": "item", "id": "itm_r9f3a", "title": "How to Do Great Work", "url": "https://paulgraham.com/greatwork.html", "site_name": "paulgraham.com", "author": { "object": "author", "id": "aut_p4w7q", "name": "Paul Graham" }, "status": "queue", "is_favorite": false, "content_type": "article", "word_count": 11842, "reading_progress": 0.35, "image_url": "https://cdn.getmatter.com/images/itm_r9f3a.jpg", "excerpt": "Paul Graham explores what it takes to do great work...", "library_position": 58974321000, "inbox_position": null, "tags": [ { "object": "tag", "id": "tag_n5j2x", "name": "essays" } ], "updated_at": "2026-03-30T19:15:00Z" } ``` ```json 404 theme={null} { "error": { "code": "not_found", "message": "No item found with ID itm_abc123." } } ``` # List Items Source: https://docs.getmatter.com/api/items/list GET /v1/items Returns a paginated list of items in your library. ## Query Parameters Filter by item status. Comma-separated for multiple: `queue,archive`. Values: `inbox`, `queue`, `archive`, or `all`. Sort order for results. Values: * `updated` — Sort by last-updated timestamp (default). Best for [incremental sync](/api/pagination#incremental-sync). * `library_position` — Sort by the item's library position (manual queue ordering). Items without a library entry sort last. * `inbox_position` — Sort by the item's inbox feed position (newest first). Items not in the inbox sort last. No status filter is required for position orderings. All items include `library_position` and `inbox_position` fields regardless of the order used, enabling clients to sort locally after incremental sync. Filter to favorited items only. Filter to items with a specific tag ID. Comma-separated for multiple: `tag_n5j2x,tag_k3m9p` (returns items matching **any** of the tags). Filter by content type. Comma-separated for multiple: `article,podcast`. Values: `article`, `video`, `podcast`, `pdf`, `tweet`, `newsletter`. ISO 8601 timestamp. Return only items updated after this time. Useful for [incremental sync](/api/pagination#incremental-sync). An item's `updated_at` reflects **any** change to the item or its associated data — status changes, reading progress, favorites, tag additions/removals, new annotations, and content re-extraction all advance the timestamp. For inbox items that have never been interacted with, `updated_at` is the time the item appeared in your inbox. Number of items per page. Min 1, max 100. Cursor for the next page of results. Obtained from `next_cursor` in a previous response. ## Response Always `"list"`. Array of item objects. See [Get Item](/api/items/get) for the full item schema. Whether there are more results after this page. Cursor to fetch the next page. `null` when there are no more results. ```bash cURL theme={null} curl "https://api.getmatter.com/public/v1/items?status=queue&limit=10" \ -H "Authorization: Bearer mat_your_token_here" ``` ```python Python theme={null} response = requests.get( "https://api.getmatter.com/public/v1/items", headers={"Authorization": f"Bearer {token}"}, params={"status": "queue", "limit": 10} ) items = response.json() ``` ```javascript JavaScript theme={null} const response = await fetch( "https://api.getmatter.com/public/v1/items?status=queue&limit=10", { headers: { Authorization: `Bearer ${token}` } } ); const items = await response.json(); ``` ```json 200 theme={null} { "object": "list", "results": [ { "object": "item", "id": "itm_r9f3a", "title": "How to Do Great Work", "url": "https://paulgraham.com/greatwork.html", "site_name": "paulgraham.com", "author": { "object": "author", "id": "aut_p4w7q", "name": "Paul Graham" }, "status": "queue", "is_favorite": false, "content_type": "article", "word_count": 11842, "reading_progress": 0.35, "image_url": "https://cdn.getmatter.com/images/itm_r9f3a.jpg", "library_position": 58974321000, "inbox_position": null, "tags": [ { "object": "tag", "id": "tag_n5j2x", "name": "essays" } ], "updated_at": "2026-03-30T19:15:00Z" } ], "has_more": true, "next_cursor": "eyJpZCI6MTIzNH0=" } ``` # Update Item Source: https://docs.getmatter.com/api/items/update PATCH /v1/items/{id} Update an item's properties. ## Path Parameters The item ID. Example: `itm_r9f3a`. ## Body Parameters All fields are optional. Only include the fields you want to change. Set to `queue` or `archive`. Inbox items can be moved to `queue` or `archive`, but items cannot be moved back to `inbox`. Set to `true` to favorite, `false` to unfavorite. Reading progress as a float from `0.0` to `1.0`. ## Response Returns the updated item. ```bash cURL theme={null} curl -X PATCH https://api.getmatter.com/public/v1/items/itm_r9f3a \ -H "Authorization: Bearer mat_your_token_here" \ -H "Content-Type: application/json" \ -d '{"status": "archive", "is_favorite": true}' ``` ```python Python theme={null} response = requests.patch( "https://api.getmatter.com/public/v1/items/itm_r9f3a", headers={ "Authorization": f"Bearer {token}", "Content-Type": "application/json" }, json={"status": "archive", "is_favorite": True} ) item = response.json() ``` ```json 200 theme={null} { "object": "item", "id": "itm_r9f3a", "title": "How to Do Great Work", "url": "https://paulgraham.com/greatwork.html", "status": "archive", "is_favorite": true, "reading_progress": 0.75, "updated_at": "2026-03-30T20:00:00Z" } ``` # Pagination Source: https://docs.getmatter.com/api/pagination Page through results with cursor-based pagination. All list endpoints return paginated results using cursor-based pagination. This approach is stable even when items are added or removed between requests. ## How it works Every list response includes pagination metadata: ```json theme={null} { "object": "list", "results": [...], "has_more": true, "next_cursor": "eyJpZCI6MTIzNH0=" } ``` | Field | Type | Description | | ------------- | -------------- | ---------------------------------------------------------------------------------- | | `results` | array | The page of results. | | `has_more` | boolean | `true` if there are more results after this page. | | `next_cursor` | string \| null | Pass this as `cursor` to get the next page. `null` when there are no more results. | ## Paginating through results To get all items, keep requesting with the `cursor` parameter until `has_more` is `false`: ```bash theme={null} # First page curl "https://api.getmatter.com/public/v1/items?limit=50" \ -H "Authorization: Bearer $MATTER_TOKEN" # Next page (use next_cursor from previous response) curl "https://api.getmatter.com/public/v1/items?limit=50&cursor=eyJpZCI6MTIzNH0=" \ -H "Authorization: Bearer $MATTER_TOKEN" ``` ```python Python example theme={null} import requests url = "https://api.getmatter.com/public/v1/items" headers = {"Authorization": f"Bearer {token}"} params = {"limit": 50} all_items = [] while True: response = requests.get(url, headers=headers, params=params).json() all_items.extend(response["results"]) if not response["has_more"]: break params["cursor"] = response["next_cursor"] print(f"Fetched {len(all_items)} items") ``` ## Page size Control page size with the `limit` parameter: | Parameter | Default | Min | Max | | --------- | ------- | --- | --- | | `limit` | 25 | 1 | 100 | ## Incremental sync Use `updated_since` to fetch only items that changed after a given timestamp. This is the most efficient way to keep a local copy of your library in sync. ```bash theme={null} # Get everything changed since your last sync curl "https://api.getmatter.com/public/v1/items?updated_since=2026-03-29T00:00:00Z" \ -H "Authorization: Bearer $MATTER_TOKEN" ``` An item's `updated_at` reflects **any** change to the item or its associated data — status changes, reading progress, favorites, tag additions/removals, new annotations, and content re-extraction all advance the timestamp. For inbox items that have never been interacted with, `updated_at` is the time the item appeared in your inbox. The `updated_since` parameter filters by `updated_at` and works with all other filters (`status`, `tag`, etc.). Combine it with pagination to sync large deltas: ```python Python example theme={null} from datetime import datetime last_sync = "2026-03-29T00:00:00Z" params = {"updated_since": last_sync, "limit": 100} changed_items = [] while True: response = requests.get(url, headers=headers, params=params).json() changed_items.extend(response["results"]) if not response["has_more"]: break params["cursor"] = response["next_cursor"] # Save the current time as your new sync checkpoint new_sync = datetime.utcnow().isoformat() + "Z" ``` Store the timestamp *before* you start syncing. If the sync fails partway through, you can retry from the same checkpoint without missing changes. ## Multi-value filters Several filter parameters accept comma-separated values to match any of the given options: ```bash theme={null} # Items in queue OR archive curl "https://api.getmatter.com/public/v1/items?status=queue,archive" \ -H "Authorization: Bearer $MATTER_TOKEN" # Articles OR podcasts curl "https://api.getmatter.com/public/v1/items?content_type=article,podcast" \ -H "Authorization: Bearer $MATTER_TOKEN" # Items with any of these tags curl "https://api.getmatter.com/public/v1/items?tag=tag_n5j2x,tag_k3m9p" \ -H "Authorization: Bearer $MATTER_TOKEN" ``` Multi-value filters use **OR** logic — an item matches if it has any of the specified values. ## Ordering By default, items are ordered by `updated_at` descending (most recently changed first). This is optimized for incremental sync workflows. You can also request **position ordering** to get items in the same order shown in the app: ```bash theme={null} # Queue in manual order (as arranged in the app) curl "https://api.getmatter.com/public/v1/items?status=queue&order=library_position" \ -H "Authorization: Bearer $MATTER_TOKEN" # All library items (queue + archive) in manual order curl "https://api.getmatter.com/public/v1/items?order=library_position" \ -H "Authorization: Bearer $MATTER_TOKEN" # Inbox in feed order curl "https://api.getmatter.com/public/v1/items?order=inbox_position" \ -H "Authorization: Bearer $MATTER_TOKEN" ``` | `order` value | Description | | ------------------ | -------------------------------------------------------------------------------------------- | | `updated` | Sort by last-updated timestamp (default). Works with all status filters and `updated_since`. | | `library_position` | Sort by library position (manual queue ordering). Items without a library entry sort last. | | `inbox_position` | Sort by inbox feed position (newest first). Items not in the inbox sort last. | No status filter is required for position orderings — items without a position sort last. ### Position fields and incremental sync Every item includes `library_position` and `inbox_position` fields, regardless of the `order` parameter used. This means you can use `order=updated` with `updated_since` for efficient incremental sync, and still use the position fields to sort items locally into app order: ```python theme={null} # Incremental sync — fetches only changed items params = {"updated_since": last_sync, "limit": 100} changed = fetch_all_pages(params) # Update local cache with changed items for item in changed: local_db[item["id"]] = item # Display in app order using position fields queue_items = sorted( [i for i in local_db.values() if i["status"] == "queue"], key=lambda i: i["library_position"] or 0, reverse=True, ) ``` Annotations, tags, and other list endpoints always use `updated_at` ordering. # Quickstart Source: https://docs.getmatter.com/api/quickstart Save your first article and retrieve your library in under 5 minutes. This guide walks you through the basics: authenticating, saving an item, listing your library, and creating an annotation. ## Prerequisites * A Matter account with an active [Pro subscription](https://web.getmatter.com/settings) * An [API token](/api/authentication) Set your token as an environment variable so you can copy-paste the examples: ```bash theme={null} export MATTER_TOKEN="mat_your_token_here" ``` ## 1. Verify your token ```bash theme={null} curl https://api.getmatter.com/public/v1/me \ -H "Authorization: Bearer $MATTER_TOKEN" ``` ```json Response theme={null} { "object": "account", "id": "act_k8x2m", "name": "Jane Smith", "email": "jane@example.com", "is_pro": true, "rate_limit": { "read": 120, "write": 30 } } ``` ## 2. Save an article ```bash theme={null} curl -X POST https://api.getmatter.com/public/v1/items \ -H "Authorization: Bearer $MATTER_TOKEN" \ -H "Content-Type: application/json" \ -d '{"url": "https://paulgraham.com/greatwork.html", "status": "queue"}' ``` ```json Response theme={null} { "object": "item", "id": "itm_r9f3a", "title": "How to Do Great Work", "url": "https://paulgraham.com/greatwork.html", "author": { "object": "author", "id": "aut_p4w7q", "name": "Paul Graham" }, "status": "queue", "processing_status": "completed", "is_favorite": false, "content_type": "article", "word_count": 11842, "reading_progress": 0.0, "image_url": null, "tags": [], "updated_at": "2026-03-30T18:30:00Z" } ``` If `processing_status` is `"processing"`, the content is being extracted in the background. Poll `GET /items/{id}` until it becomes `"completed"` (typically 20-60 seconds). If the URL is already in your library, the existing item is returned instead of creating a duplicate. The response status will be `200` instead of `201`. ## 3. List your library ```bash theme={null} curl "https://api.getmatter.com/public/v1/items?status=queue&limit=5" \ -H "Authorization: Bearer $MATTER_TOKEN" ``` ```json Response theme={null} { "object": "list", "results": [ { "object": "item", "id": "itm_r9f3a", "title": "How to Do Great Work", "status": "queue", "content_type": "article" } ], "has_more": false, "next_cursor": null } ``` ## 4. Tag the article ```bash theme={null} curl -X POST https://api.getmatter.com/public/v1/items/itm_r9f3a/tags \ -H "Authorization: Bearer $MATTER_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "essays"}' ``` ```json Response theme={null} { "object": "tag", "id": "tag_n5j2x", "name": "essays" } ``` ## 5. Archive when done ```bash theme={null} curl -X PATCH https://api.getmatter.com/public/v1/items/itm_r9f3a \ -H "Authorization: Bearer $MATTER_TOKEN" \ -H "Content-Type: application/json" \ -d '{"status": "archive"}' ``` ```json Response theme={null} { "object": "item", "id": "itm_r9f3a", "status": "archive", "updated_at": "2026-03-30T20:30:00Z" } ``` ## Next steps Efficiently page through large libraries. Pull only items that changed since your last sync. Understand request quotas and how to stay within them. Every endpoint, parameter, and response field. # Rate Limits Source: https://docs.getmatter.com/api/rate-limits Understand request quotas and how to handle rate limiting. The Matter API enforces per-user rate limits to ensure fair usage and protect the service. ## Limits | Operation | Limit | Applies to | | ------------ | ---------------- | --------------------------------------- | | **Read** | 120 requests/min | All `GET` requests | | **Write** | 30 requests/min | `POST`, `PATCH`, `DELETE` requests | | **Save** | 10 requests/min | `POST /v1/items` (saving new URLs) | | **Search** | 30 requests/min | `GET /v1/search` | | **Markdown** | 20 requests/min | `GET` requests with `?include=markdown` | | **Burst** | 5 requests/sec | All requests (short-term ceiling) | Save requests have a lower limit because each save triggers background content extraction (fetching, parsing, and processing the URL). Markdown requests count against both the **read** and **markdown** limits because these responses are significantly larger and more expensive to serve. Limits are applied per API token (i.e., per user account). ## Rate limit headers Every response includes headers showing your current quota: ``` X-RateLimit-Limit: 120 X-RateLimit-Remaining: 117 X-RateLimit-Reset: 1711814400 ``` | Header | Description | | ----------------------- | ------------------------------------------------ | | `X-RateLimit-Limit` | Maximum requests allowed in the current window. | | `X-RateLimit-Remaining` | Requests remaining in the current window. | | `X-RateLimit-Reset` | Unix timestamp (seconds) when the window resets. | ## Handling 429 responses When you exceed the limit, the API returns `429 Too Many Requests` with a `Retry-After` header: ```json theme={null} { "error": { "code": "rate_limited", "message": "Rate limit exceeded. Retry after 12 seconds." } } ``` ``` HTTP/1.1 429 Too Many Requests Retry-After: 12 X-RateLimit-Limit: 120 X-RateLimit-Remaining: 0 X-RateLimit-Reset: 1711814400 ``` ### Recommended retry strategy ```python theme={null} import time import requests def api_request(url, headers, max_retries=3): for attempt in range(max_retries): response = requests.get(url, headers=headers) if response.status_code != 429: return response retry_after = int(response.headers.get("Retry-After", 10)) time.sleep(retry_after) raise Exception("Rate limit exceeded after retries") ``` Do not retry immediately or in a tight loop. Always respect the `Retry-After` value. Clients that ignore rate limits may have their tokens temporarily suspended. ## Best practices The `updated_since` parameter on list endpoints dramatically reduces the number of requests needed to stay in sync. Fetch everything once, then sync only changes. Set `limit=100` (the maximum) to reduce the number of requests needed to paginate through results. Store items locally and only refetch when needed. The `updated_at` field tells you if an item has changed. If you're tagging many items, space your requests rather than firing them all at once. # List Reading Sessions Source: https://docs.getmatter.com/api/reading-sessions/list GET /v1/reading_sessions Returns a paginated list of reading sessions for the authenticated user. Each session records a single reading period with a timestamp and duration. Use these to compute reading streaks, daily totals, or other time-based statistics client-side. ## Query Parameters Only return sessions on or after this ISO 8601 datetime. Useful for incremental sync. Example: `2026-04-01T00:00:00Z`. Number of sessions per page. Min 1, max 100. Cursor for the next page of results. ## Response Always `"list"`. Array of reading session objects, ordered by date descending (newest first). Always `"reading_session"`. Reading session ID (e.g. `rs_k8x2m`). When the session occurred (ISO 8601, UTC). Duration of the session in seconds. Whether there are more results. Cursor for the next page. ```bash cURL theme={null} curl "https://api.getmatter.com/public/v1/reading_sessions" \ -H "Authorization: Bearer mat_your_token_here" ``` ```bash cURL (with since filter) theme={null} curl "https://api.getmatter.com/public/v1/reading_sessions?since=2026-04-01T00:00:00Z" \ -H "Authorization: Bearer mat_your_token_here" ``` ```python Python theme={null} response = requests.get( "https://api.getmatter.com/public/v1/reading_sessions", headers={"Authorization": f"Bearer {token}"}, params={"since": "2026-04-01T00:00:00Z"} ) sessions = response.json() ``` ```json 200 theme={null} { "object": "list", "results": [ { "object": "reading_session", "id": "rs_k8x2m", "date": "2026-04-09T14:23:00Z", "seconds_read": 180 }, { "object": "reading_session", "id": "rs_j7w1n", "date": "2026-04-09T08:12:00Z", "seconds_read": 162 }, { "object": "reading_session", "id": "rs_h6v0p", "date": "2026-04-08T21:45:00Z", "seconds_read": 480 } ], "has_more": true, "next_cursor": "eyJ1YSI6MTc..." } ``` # Search Source: https://docs.getmatter.com/api/search GET /v1/search Full-text search across Matter, grouped by type. Search across Matter. Results are grouped by type, each with independent pagination. Currently supports `items`; more types will be added in future releases. ## Query Parameters Search query string (min 2 characters). Supports operators: * `"exact phrase"` — required phrase match * `-excluded` — exclude articles containing a term * `by:author` — filter by author or publisher name * `site:domain` — filter by domain or publisher * `title:word` — match in title only Examples: `machine learning`, `"deep work"`, `by:graham site:paulgraham.com` Comma-separated list of result types to include. Currently supported: `items`. Filter for **item** results. Restricts results to items with the given status. Comma-separated for multiple values. Omit to search all content. Only applies when `items` is in the `type` parameter. * `queue` — queue items only * `archive` — archived items only * `queue,archive` — both queue and archive Maximum results per type. Min 1, max 100. Cursor for the next page of results. Obtained from `next_cursor` in a previous response. ## Response Always `"search_results"`. Matching items, ranked by relevance. Present when `items` is in the `type` parameter. Always `"list"`. Array of item objects ranked by relevance. Always `"item"`. Prefixed item ID (e.g. `itm_r9f3a`). The item's title. Original URL of the content. The source website name. The item's author, if known. Always `"author"`. Prefixed author ID (e.g. `aut_p4w7q`). Author name. Status: `inbox`, `queue`, or `archive`. `null` when the item has no status. Type of content: `article`, `podcast`, `pdf`, or `tweet`. Content extraction status: `processing` or `completed`. Whether the item is favorited. Reading progress from `0.0` to `1.0`. Estimated word count. URL of the item's hero image. Short excerpt or description. Position in the library. `null` if not in the library. Position in the inbox feed. `null` if not in the inbox. Tags applied to this item. ISO 8601 timestamp of the last change. Whether there are more results after this page. Cursor for the next page, or `null`. ```bash cURL theme={null} curl "https://api.getmatter.com/public/v1/search?query=machine+learning&type=items&status=queue" \ -H "Authorization: Bearer mat_your_token_here" ``` ```python Python theme={null} response = requests.get( "https://api.getmatter.com/public/v1/search", headers={"Authorization": f"Bearer {token}"}, params={"query": "machine learning", "type": "items", "status": "queue"} ) data = response.json() for item in data["items"]["results"]: print(item["title"]) ``` ```javascript JavaScript theme={null} const response = await fetch( "https://api.getmatter.com/public/v1/search?query=machine+learning&type=items&status=queue", { headers: { Authorization: `Bearer ${token}` } } ); const data = await response.json(); data.items.results.forEach(item => console.log(item.title)); ``` ```json 200 theme={null} { "object": "search_results", "items": { "object": "list", "results": [ { "object": "item", "id": "itm_r9f3a", "title": "Introduction to Machine Learning", "url": "https://example.com/intro-ml", "site_name": "example.com", "author": { "object": "author", "id": "aut_p4w7q", "name": "Jane Smith" }, "status": "queue", "is_favorite": false, "content_type": "article", "processing_status": "completed", "word_count": 4200, "reading_progress": 0.35, "image_url": null, "library_position": 58974321000, "inbox_position": null, "tags": [], "updated_at": "2026-03-30T19:15:00Z" }, { "object": "item", "id": "itm_k4m2n", "title": "Neural Networks from Scratch", "url": "https://example.com/nn-scratch", "site_name": "example.com", "author": null, "status": null, "is_favorite": false, "content_type": "article", "processing_status": "completed", "word_count": 8100, "reading_progress": 0.0, "image_url": null, "library_position": null, "inbox_position": null, "tags": [], "updated_at": "2026-03-28T12:00:00Z" } ], "has_more": false, "next_cursor": null } } ``` # Add Tag to Item Source: https://docs.getmatter.com/api/tags/add POST /v1/items/{item_id}/tags Add a tag to an item. Creates the tag if it doesn't exist. ## Path Parameters The item ID. Example: `itm_r9f3a`. ## Body Parameters The tag name. Case-insensitive. If a tag with this name already exists, it will be reused. ## Response Returns the tag with status `201` if newly created, or `200` if the tag was already on this item. ```bash cURL theme={null} curl -X POST https://api.getmatter.com/public/v1/items/itm_r9f3a/tags \ -H "Authorization: Bearer mat_your_token_here" \ -H "Content-Type: application/json" \ -d '{"name": "essays"}' ``` ```python Python theme={null} response = requests.post( "https://api.getmatter.com/public/v1/items/itm_r9f3a/tags", headers={ "Authorization": f"Bearer {token}", "Content-Type": "application/json" }, json={"name": "essays"} ) tag = response.json() ``` ```json 201 theme={null} { "object": "tag", "id": "tag_n5j2x", "name": "essays", "item_count": 43, "created_at": "2025-01-15T10:00:00Z" } ``` # Delete Tag Source: https://docs.getmatter.com/api/tags/delete DELETE /v1/tags/{id} Permanently delete a tag and remove it from all items. ## Path Parameters The tag ID. Example: `tag_n5j2x`. ## Response Returns `204 No Content` on success. The tag is removed from all items and permanently deleted. This action is irreversible. All items that had this tag will have it removed. ```bash cURL theme={null} curl -X DELETE https://api.getmatter.com/public/v1/tags/tag_n5j2x \ -H "Authorization: Bearer mat_your_token_here" ``` ```python Python theme={null} response = requests.delete( "https://api.getmatter.com/public/v1/tags/tag_n5j2x", headers={"Authorization": f"Bearer {token}"} ) assert response.status_code == 204 ``` ```json 204 theme={null} (No content) ``` # List Tags Source: https://docs.getmatter.com/api/tags/list GET /v1/tags Returns all tags in your library. ## Query Parameters Number of tags per page. Min 1, max 100. Cursor for the next page of results. ## Response Always `"list"`. Array of tag objects. Always `"tag"`. Tag ID. Tag name. Number of items with this tag. ISO 8601 timestamp. Whether there are more results. Cursor for the next page. ```bash cURL theme={null} curl https://api.getmatter.com/public/v1/tags \ -H "Authorization: Bearer mat_your_token_here" ``` ```python Python theme={null} response = requests.get( "https://api.getmatter.com/public/v1/tags", headers={"Authorization": f"Bearer {token}"} ) tags = response.json() ``` ```json 200 theme={null} { "object": "list", "results": [ { "object": "tag", "id": "tag_n5j2x", "name": "essays", "item_count": 42, "created_at": "2025-01-15T10:00:00Z" }, { "object": "tag", "id": "tag_k3m9p", "name": "tech", "item_count": 87, "created_at": "2025-02-20T14:30:00Z" } ], "has_more": false, "next_cursor": null } ``` # Remove Tag from Item Source: https://docs.getmatter.com/api/tags/remove DELETE /v1/items/{item_id}/tags/{tag_id} Remove a tag from an item. ## Path Parameters The item ID. Example: `itm_r9f3a`. The tag ID. Example: `tag_n5j2x`. ## Response Returns `204 No Content` on success. The tag itself is not deleted — only the association with this item is removed. ```bash cURL theme={null} curl -X DELETE https://api.getmatter.com/public/v1/items/itm_r9f3a/tags/tag_n5j2x \ -H "Authorization: Bearer mat_your_token_here" ``` ```python Python theme={null} response = requests.delete( "https://api.getmatter.com/public/v1/items/itm_r9f3a/tags/tag_n5j2x", headers={"Authorization": f"Bearer {token}"} ) assert response.status_code == 204 ``` ```json 204 theme={null} (No content) ``` # Rename Tag Source: https://docs.getmatter.com/api/tags/update PATCH /v1/tags/{id} Rename a tag. The new name applies to all items that have this tag. ## Path Parameters The tag ID. Example: `tag_n5j2x`. ## Body Parameters The new tag name. ## Response Returns the updated tag. ```bash cURL theme={null} curl -X PATCH https://api.getmatter.com/public/v1/tags/tag_n5j2x \ -H "Authorization: Bearer mat_your_token_here" \ -H "Content-Type: application/json" \ -d '{"name": "long-reads"}' ``` ```python Python theme={null} response = requests.patch( "https://api.getmatter.com/public/v1/tags/tag_n5j2x", headers={ "Authorization": f"Bearer {token}", "Content-Type": "application/json" }, json={"name": "long-reads"} ) tag = response.json() ``` ```json 200 theme={null} { "object": "tag", "id": "tag_n5j2x", "name": "long-reads", "item_count": 42, "created_at": "2025-01-15T10:00:00Z" } ``` ```json 409 theme={null} { "error": { "code": "conflict", "message": "A tag with this name already exists.", "field": "name" } } ``` # Versioning Source: https://docs.getmatter.com/api/versioning How the Matter API is versioned and how to handle upgrades. The API uses URL path versioning. The current version is `v1`. ## Base URL ``` https://api.getmatter.com/public/v1/ ``` The version is part of every endpoint URL: ``` GET https://api.getmatter.com/public/v1/items POST https://api.getmatter.com/public/v1/items GET https://api.getmatter.com/public/v1/me ``` ## Compatibility promise Within a version, we will **not** make breaking changes. You can rely on: * Existing fields will not be removed or renamed * Existing endpoints will not be removed * Existing error codes will not change meaning * Response shapes will not change We **may** add new, non-breaking changes within a version: * New optional fields on existing resources * New endpoints * New optional query parameters * New error codes for new failure modes Write your client code to ignore unknown fields. This ensures you're forward-compatible when we add new response fields. ## Deprecation policy When we release a new version: 1. The previous version enters a **deprecation period** of at least 6 months 2. Deprecated versions include a `Sunset` header with the retirement date 3. We'll notify you via email before sunsetting a version ``` Sunset: Sat, 01 Nov 2027 00:00:00 GMT Deprecation: true ``` ## Current versions | Version | Status | Base URL | | ------- | ---------- | -------------------------------------- | | `v1` | **Active** | `https://api.getmatter.com/public/v1/` | # Commands Source: https://docs.getmatter.com/cli/commands Full reference for every Matter CLI command. All commands output JSON by default. Add `--plain` for human-readable output. ## Account ```bash theme={null} matter account # JSON matter account --plain # Human-readable ``` Returns your account info including name, email, and Pro status. ## Items ### List items ```bash theme={null} matter items list [options] ``` | Option | Description | | ----------------- | ------------------------------------------------------------------------------------------------------------- | | `--status` | Filter by status: `inbox`, `queue`, `archive`, `all` | | `--content-type` | Filter by type: `article`, `podcast`, `video`, `pdf`, `tweet`, `email` | | `--favorite` | Only favorited items | | `--tag` | Filter by tag ID | | `--order` | Sort order: `updated`, `library_position`, `inbox_position` (position orderings use app ordering, nulls last) | | `--updated-since` | Filter by updated date (ISO 8601) | | `--limit` | Results per page (default 25, max 100) | | `--cursor` | Pagination cursor from previous response | | `--all` | Fetch all pages | | `--plain` | Human-readable output | ```bash theme={null} matter items list --status queue --plain matter items list --content-type article --favorite --limit 10 matter items list --status archive --all ``` ### Get an item ```bash theme={null} matter items get matter items get itm_r9f3a --plain ``` ### Save a URL ```bash theme={null} matter items save --url [--status queue|archive] ``` ```bash theme={null} matter items save --url "https://example.com/article" matter items save --url "https://example.com/article" --status queue ``` ### Update an item ```bash theme={null} matter items update [options] ``` | Option | Description | | ------------ | --------------------------------- | | `--status` | Move to `queue` or `archive` | | `--favorite` | Set favorite (`true` or `false`) | | `--progress` | Reading progress (`0.0` to `1.0`) | ```bash theme={null} matter items update itm_r9f3a --status archive matter items update itm_r9f3a --favorite true ``` ### Delete an item ```bash theme={null} matter items delete ``` ## Search ```bash theme={null} matter search --type [options] ``` Full-text search across Matter, ranked by relevance. Results are grouped by type. | Option | Description | | ---------- | ---------------------------------------------------------------------- | | `--type` | **(required)** Result types, comma-separated (e.g. `items`) | | `--status` | Filter items by status: `queue`, `archive`. Omit to search all content | | `--limit` | Results per page (default 25, max 100) | | `--cursor` | Pagination cursor from previous response | | `--all` | Fetch all pages | | `--plain` | Human-readable output | ```bash theme={null} matter search "machine learning" --type items --plain matter search "by:graham" --type items --status queue matter search "\"deep work\"" --type items --all matter search "site:nytimes climate" --type items --limit 10 ``` ### Search operators | Operator | Description | Example | | ------------- | -------------------------- | ------------------ | | `"phrase"` | Exact phrase match | `"deep learning"` | | `-term` | Exclude term | `-podcast` | | `by:name` | Filter by author/publisher | `by:graham` | | `site:domain` | Filter by domain | `site:nytimes.com` | | `title:word` | Match in title only | `title:review` | ## Annotations ### List annotations ```bash theme={null} matter annotations list --item [options] ``` | Option | Description | | ---------- | ---------------------------------------- | | `--item` | **(required)** Item ID | | `--limit` | Results per page (default 25, max 100) | | `--cursor` | Pagination cursor from previous response | | `--all` | Fetch all pages | | `--plain` | Human-readable output | ```bash theme={null} matter annotations list --item itm_r9f3a --plain matter annotations list --item itm_r9f3a --all ``` ### Get an annotation ```bash theme={null} matter annotations get matter annotations get ann_k3m9p ``` ### Update an annotation ```bash theme={null} matter annotations update --note "Updated note" ``` ### Delete an annotation ```bash theme={null} matter annotations delete ``` ## Tags ### List all tags ```bash theme={null} matter tags list matter tags list --plain ``` ### Rename a tag ```bash theme={null} matter tags rename --name "new name" ``` ### Delete a tag ```bash theme={null} matter tags delete ``` ### Add a tag to an item ```bash theme={null} matter tags add --item --name "tag name" ``` Creates the tag if it doesn't exist. ### Remove a tag from an item ```bash theme={null} matter tags remove --item --tag ``` ## Auth ### Log in ```bash theme={null} matter login # Opens browser to get token matter login # Pass token directly ``` ### Interactive TUI ```bash theme={null} matter tui # Launch the interactive terminal UI ``` Also launches when you run `matter` with no arguments. See [Interactive TUI](/cli/tui) for keyboard shortcuts. ### Self-update The CLI auto-updates in the background. New releases are downloaded while your command runs and applied on the next invocation. To update immediately instead: ```bash theme={null} matter update # Update now (instead of waiting for next run) matter version # Show current version ``` ## Readonly mode Enable readonly mode to prevent write operations (save, update, delete): ```bash theme={null} # Toggle in TUI settings, or edit ~/.config/matter/config.json ``` When enabled, all write commands will be rejected with an error. # Matter CLI Source: https://docs.getmatter.com/cli/index Terminal client for your Matter reading library — CLI mode for scripting and an interactive TUI for browsing. Save articles, search your library, and manage tags without leaving the terminal. All commands output JSON by default, making it easy to pipe into `jq` or other tools. An interactive TUI is also included for visual browsing. The CLI requires a Matter Pro subscription. [Upgrade to Pro](https://web.getmatter.com/settings) to get started. ## Resources Install the CLI, authenticate, and run your first commands. Full reference for every CLI command. Browse your library visually in the terminal. # Quickstart Source: https://docs.getmatter.com/cli/quickstart Install and use the Matter CLI to manage your reading library from the terminal. The Matter CLI lets you manage your library from the terminal. It works in two modes: **CLI mode** for scripting and automation (JSON output by default), and an **interactive TUI** for browsing your library visually. ## Install ```bash theme={null} curl -fsSL https://cli.getmatter.com/install.sh | sh ``` ```powershell theme={null} irm https://cli.getmatter.com/install.ps1 | iex ``` ```bash theme={null} git clone https://github.com/getmatterapp/matter-cli.git cd matter-cli bun install bun run src/cli.tsx --help ``` ## Authenticate Log in with your Matter API token: ```bash theme={null} # Opens browser to copy your API token matter login # Or pass a token directly matter login mat_yourtoken # Piped input (for automation) echo "$MATTER_TOKEN" | matter login ``` Your token is stored at `~/.config/matter/config.json`. See [Authentication](/api/authentication) for how to generate a token. ## Quick examples ```bash theme={null} # Check your account matter account --plain # List your queue matter items list --status queue --plain # Save a URL matter items save --url "https://paulgraham.com/greatwork.html" # Get a specific item with full details matter items get itm_r9f3a # List annotations on an item matter annotations list --item itm_r9f3a # Tag an item matter tags add --item itm_r9f3a --name "essays" # Archive an item matter items update itm_r9f3a --status archive ``` ## Output formats **JSON (default)** — structured output for scripting and piping: ```json theme={null} { "object": "list", "results": [...], "has_more": true, "next_cursor": "cur_abc123" } ``` **Plain text (`--plain`)** — human-readable table output: ``` itm_r9f3a How to Do Great Work paulgraham.com queue 35% itm_k8w2p The Art of Finishing example.com archive 100% ``` Errors go to stderr. Exit code 0 for success, 1 for errors. ## Pagination List commands support cursor-based pagination: ```bash theme={null} # First page matter items list --limit 10 # Next page (use next_cursor from previous response) matter items list --limit 10 --cursor # Fetch all pages at once matter items list --all ``` ## Updating The CLI updates itself automatically. New releases are downloaded in the background and applied on the next run. To update immediately: ```bash theme={null} matter update ``` ## Next steps Full reference for every CLI command. Browse your library visually in the terminal. # Interactive TUI Source: https://docs.getmatter.com/cli/tui Browse and manage your Matter library visually in the terminal. Launch the interactive TUI by running `matter` with no arguments, or explicitly with `matter tui`: ```bash theme={null} matter matter tui ``` The TUI provides a visual interface for browsing your library, reading items, and managing tags -- all without leaving the terminal. ## Global shortcuts | Key | Action | | ------------ | ---------------------------------------- | | `q` | Quit | | `Escape` | Go back | | `/` | Open search | | `d` | Cycle color mode (system / dark / light) | | `j` / `Down` | Move down | | `k` / `Up` | Move up | | `Enter` | Select / confirm | ## Command palette The landing screen. Arrow keys to navigate, `Enter` to select. Available commands: **Search**, **Browse Inbox**, **Browse Queue**, **Browse Archive**, **Browse All Items**, **Settings**. ## Item list Browse items in a list with status, progress, and site info. | Key | Action | | ------------ | ---------------- | | `j` / `Down` | Next item | | `k` / `Up` | Previous item | | `Enter` | Open item detail | | `e` | Archive item | | `s` | Save to queue | | `f` | Toggle favorite | Scrolling near the bottom auto-loads the next page. ## Item detail View article content with a sidebar showing metadata (author, status, type, progress, tags). Articles render as markdown in the terminal. | Key | Action | | ---------------- | -------------------------------------------- | | `Left` / `Right` | Navigate action bar | | `Enter` | Activate selected action | | `s` | Save to queue | | `e` | Archive | | `f` | Toggle favorite | | `n` | Toggle notebook panel (highlights and notes) | | `w` | Open in Matter web app | | `b` | Open original URL in browser | ## Search Type to search — results update automatically after a short delay (minimum 2 characters). Press `Enter` to focus results, then `j`/`k` to navigate and `Enter` to open. `Escape` returns to the search input (or exits search if already in input mode). Typing any character while browsing results returns to the input. | Key | Input mode | Results mode | | ------------- | ------------------- | ------------------- | | `Enter` | Focus results | Open item | | `Escape` | Exit search | Back to input | | `j` / `k` | Types normally | Navigate results | | `Up` / `Down` | Move selection | Move selection | | `Tab` | Cycle status filter | Cycle status filter | ### Search operators Operators can be typed directly into the query: | Operator | Description | Example | | ------------- | -------------------------- | ------------------ | | `"phrase"` | Exact phrase match | `"deep learning"` | | `-term` | Exclude term | `-podcast` | | `by:name` | Filter by author/publisher | `by:graham` | | `site:domain` | Filter by domain | `site:nytimes.com` | | `title:word` | Match in title only | `title:review` | ## Settings Toggle options with `Enter`: * **Readonly Mode** — prevent write operations * **Color Mode** — system, dark, or light * **Auth Token** — shows a preview of your stored token * **Version** — current CLI version ## Configuration TUI settings are stored alongside CLI config at `~/.config/matter/config.json`. You can also toggle settings directly in the TUI's settings screen. # Matter Documentation Source: https://docs.getmatter.com/index API reference, CLI tools, and developer guides for the Matter read-later app. Matter is a read-later app for people who take reading seriously. Save articles, newsletters, PDFs, tweets, and more from anywhere — then read them in a clean, focused interface on iOS or the web. Highlight passages, take notes, and organize everything with tags. ## Resources Build custom integrations with the REST API. Save URLs, sync your library, and automate workflows. Manage your library from the terminal. Includes an interactive TUI and JSON output for scripting.