Search indexed note titles and shared summaries by keyword, or filter by calendar participant. Results contain the standard note summary plus meeting_at; use Get note to retrieve content. Filter by space_id to search a space and its folders; when folder_id is also provided, both filters apply. Each recording is a separate note. Private notes and transcripts are not searched. Only live notes with generated summaries are returned, including for compliance keys. Search coverage depends on indexing; use List notes for a complete listing. An empty body browses indexed notes without a default date window. Pages examine up to 100 index candidates, so access checks and filters may produce short or empty pages even when hasMore is true. Continue with cursor while hasMore is true. Cursors expire after 15 minutes and are bound to the API key and scope; access is rechecked on every page. After 10,000 examined candidates, completion_status is incomplete, hasMore is false, and cursor is null; narrow the search. Fetch-only keys return an empty result.

post/v1/notes/search

Request

  • Base URL
    https://public-api.granola.ai
  • Auth
    HTTP bearer

Request body

keywordsstring[]

Alternative keyword searches in titles and shared summaries. All tokens of at least one entry must match.

participantstring

Participant name, email, company or domain from calendar metadata. Filters attendance, not mentions in notes.

folder_idstring
space_idstring

Return notes in this space and its folders. Space IDs are case-insensitive. Use List spaces to discover accessible spaces. When folder_id is also provided, both filters apply.

page_sizeinteger

Maximum number of notes to return per page

cursorstring

Continue a search. Only page_size may accompany a cursor.

Example request

{
  "space_id": "spa_8kTq2mWxLp4Rz7",
  "page_size": 10
}

Response

Matching note metadata and search continuation status

hasMoreboolean required

Whether another page can be fetched using cursor.

cursorstring nullable required

The next-page cursor, or null when hasMore is false.

completion_status'more_available' | 'exhausted' | 'incomplete' required

more_available: continue with cursor. exhausted: no more matches. incomplete: the scan limit was reached; hasMore is false and cursor is null. Start a narrower search.

Example response

{
  "notes": [
    {
      "id": "not_1d3tmYTlCICgjy",
      "title": "Quarterly yoghurt budget review",
      "owner": {
        "name": "Oat Benson",
        "email": "oat@granola.ai"
      },
      "created_at": "2026-01-27T15:30:00Z",
      "updated_at": "2026-01-27T16:45:00Z"
    }
  ]
}

Changes