> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tiro.ooo/llms.txt
> Use this file to discover all available pages before exploring further.

# list_notes

> List notes by filter and optional keyword — lightweight metadata only

## Overview

`list_notes` is the lightweight tier of note discovery: it returns metadata only — title, participants, dates, source type — and is the right tool when you need to **know which notes exist** without reading their content.

When `query.keyword` is provided the result set is reordered by full-text relevance (with `createdAt` desc as tiebreaker) instead of `recordingStartAt` desc.

**Primary Use Cases:**

* "Which notes are in folder X?"
* "Which notes match keyword Y?" (just to confirm existence)
* Filtering by date range to narrow a large workspace.

**Key Features:**

* 3-tier model with [`search_notes`](./search-notes) (deep, returns documents) and [`get_note_transcript`](./get-transcript) (raw transcript).
* Cursor-based pagination on the list path.
* Excludes incomplete notes automatically — notes whose recording never started and whose title is the default placeholder are filtered out at the MCP layer.

<Tip>
  **Token efficiency.** A `list_notes` page returns \~50 tokens per note. Compared to loading documents via `search_notes` (\~1,500 tokens per note) or transcripts via `get_note_transcript` (\~3,000–5,000 tokens per note), this is the cheapest way to find what you have.
</Tip>

## Parameters

| Parameter              | Type   | Required | Description                                                                                                                                                                 |
| ---------------------- | ------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `query.keyword`        | string | Optional | Optional keyword. When present, reorders by full-text relevance.                                                                                                            |
| `workspaceGuid`        | string | Optional | Target a specific workspace (from `list_workspaces`). Omit to search across all workspaces you can access; a workspace-scoped key automatically searches its own workspace. |
| `pagination.cursor`    | string | Optional | Cursor from a previous `nextCursor`.                                                                                                                                        |
| `pagination.size`      | number | Optional | Results per page (default `20`, max `100`).                                                                                                                                 |
| `filter.folderId`      | string | Optional | Restrict to a folder (recursive — includes descendant folders).                                                                                                             |
| `filter.createdAtFrom` | string | Optional | ISO 8601 datetime, inclusive lower bound on `createdAt`.                                                                                                                    |
| `filter.createdAtTo`   | string | Optional | ISO 8601 datetime, exclusive upper bound on `createdAt`.                                                                                                                    |

### query.keyword (optional)

Switches the listing into relevance mode. Hits are scored by the server's full-text index against the note title and paragraph content. With keyword present, `nextCursor` is `null` (the deep search index doesn't carry a stable list cursor).

Keyword search works for both user-scoped and workspace-scoped API keys. Omit `workspaceGuid` to search across all workspaces you can access (a workspace-scoped key automatically searches its own workspace); pass an explicit `workspaceGuid` to target a specific one.

### workspaceGuid (optional)

Targets a specific workspace. Get available GUIDs from `list_workspaces`. Omit it to search across all workspaces you can access — a workspace-scoped key automatically searches its own workspace.

### filter.folderId (optional)

When provided, the listing is recursively scoped to the folder and all of its descendants. Folder access is authorized server-side; passing a folderId you don't have access to returns `404`.

### filter.createdAtFrom / filter.createdAtTo (optional)

Half-open `[from, to)` range filter on `createdAt`. Both accept ISO 8601 datetime with timezone (e.g., `2026-04-01T00:00:00Z`).

### pagination (optional)

`{ cursor, size }`. Default `size: 20`, max `100`. Use the `nextCursor` from the previous response to walk pages.

## Response Format

### Success Response

```json theme={"system"}
{
  "content": [
    {
      "noteGuid": "abc-123-def",
      "title": "OKR Q2 Planning",
      "webUrl": "https://platform.tiro.ooo/notes/abc-123-def",
      "createdAt": "2026-04-15T10:00:00Z",
      "updatedAt": "2026-04-15T11:30:00Z",
      "recordingDurationSeconds": 3625,
      "sourceType": "live-voice",
      "participants": [
        { "name": "Alice Kim", "email": "alice@example.com" },
        { "name": "Bob Park", "email": null }
      ]
    }
  ],
  "notes": [],
  "total": 137,
  "totalSize": 1,
  "nextCursor": "eyJvZmZzZXQiOjUwfQ=="
}
```

<Note>
  The response carries each note both under `content` (recommended) and `notes` (legacy alias). Pick whichever your client prefers and ignore the other.
</Note>

**Field Descriptions:**

| Field                                | Type           | Description                                                                                 |
| ------------------------------------ | -------------- | ------------------------------------------------------------------------------------------- |
| `content[]`                          | array          | Notes (preferred field).                                                                    |
| `content[].noteGuid`                 | string         | Unique note identifier — pass to `search_notes`, `get_note_transcript`, etc.                |
| `content[].title`                    | string         | Note title.                                                                                 |
| `content[].webUrl`                   | string         | Direct link to the note in the Tiro web app.                                                |
| `content[].createdAt`                | string         | ISO 8601 creation timestamp.                                                                |
| `content[].updatedAt`                | string         | ISO 8601 last-update timestamp.                                                             |
| `content[].recordingDurationSeconds` | number         | Recording length in seconds (`0` for non-recording sources).                                |
| `content[].sourceType`               | string         | One of `live-voice`, `recording`, `text`, `video`, `webpage`, `offline-mode`, `onboarding`. |
| `content[].participants[]`           | array          | `{ name, email }` per participant. Either may be `null`.                                    |
| `total`                              | number         | Backend's pre-filter count.                                                                 |
| `totalSize`                          | number         | Count after the MCP-side incomplete-note filter (may be smaller than `total`).              |
| `nextCursor`                         | string \| null | Cursor for the next page; `null` when no more results or when keyword search is active.     |

<Warning>
  **Pagination tip.** `total` and `totalSize` may diverge — incomplete notes counted by `total` are filtered out before `totalSize`. Don't loop with `while (totalSize < total)`; walk pages with `nextCursor` instead.
</Warning>

## Usage Examples

### Example 1: Notes in a specific folder

**Request:**

```json theme={"system"}
{
  "filter": {
    "folderId": "455765"
  }
}
```

Returns the most recent 20 complete notes in folder `455765` and its descendants.

### Example 2: Recent notes by date range

**Request:**

```json theme={"system"}
{
  "filter": {
    "createdAtFrom": "2026-04-01T00:00:00Z",
    "createdAtTo": "2026-05-01T00:00:00Z"
  },
  "pagination": {
    "size": 50
  }
}
```

### Example 3: Keyword listing (relevance-ranked)

**Request:**

```json theme={"system"}
{
  "query": {
    "keyword": "OKR"
  },
  "pagination": {
    "size": 30
  }
}
```

Returns notes whose title or paragraphs match `OKR`, ordered by relevance. The response's `nextCursor` is `null` — re-call with the same keyword and a larger `size` if you need more.

### Example 4: Paginated browse

**First page:**

```json theme={"system"}
{
  "pagination": { "size": 50 }
}
```

**Next page (using `nextCursor` from previous response):**

```json theme={"system"}
{
  "pagination": {
    "size": 50,
    "cursor": "eyJvZmZzZXQiOjUwfQ=="
  }
}
```

## When to use which tier

<AccordionGroup>
  <Accordion title="Use list_notes when…">
    You need to **know which notes exist** — by folder, by date, or by keyword presence. Returns metadata only, \~50 tokens per note. Cheapest discovery tool.
  </Accordion>

  <Accordion title="Use search_notes when…">
    You need to **understand the context behind a topic** — its decisions, action items, or the team's conclusions. Returns matched notes plus their primary documents (one-pager, custom). \~1,500 tokens per note.

    Switch from `list_notes` to [`search_notes`](./search-notes) when the LLM needs document content to answer the user's question.
  </Accordion>

  <Accordion title="Use get_note_transcript when…">
    You need to **quote exact spoken words** from the conversation. Returns the full transcript with timestamps. \~3,000–5,000 tokens per hour of meeting — last resort.

    See [`get_note_transcript`](./get-transcript).
  </Accordion>
</AccordionGroup>

## Common Errors

### Invalid datetime

<Error>
  ```json theme={"system"}
  {
    "error": "Invalid createdAtFrom format. Expected ISO 8601 datetime.",
    "code": "INVALID_DATE_FORMAT",
    "statusCode": 400
  }
  ```
</Error>

**Solution:** Use ISO 8601 datetime with timezone (e.g., `2026-04-01T00:00:00Z`).

## Token Usage

| Mode                                    | Tokens per note                   |
| --------------------------------------- | --------------------------------- |
| `list_notes` (metadata only)            | \~50                              |
| `search_notes` (with documents)         | \~1,500                           |
| `get_note_transcript` (full transcript) | \~3,000–5,000 per hour of meeting |

<Tip>
  **Discovery flow.** Start with `list_notes` to find the noteGuids you care about. Switch to `search_notes` only when you need document content. Reach for `get_note_transcript` only when verbatim quoting is required.
</Tip>
