> For the complete documentation index, see [llms.txt](https://docs.zero.inc/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.zero.inc/features/api/meetings.md).

# Meetings

Read meetings (calendar events) and their transcripts. Only read (`GET`) access is exposed via the API — meetings and transcripts cannot be created, updated, or deleted.

#### Transcripts are segment-grained

A transcript is stored as many rows — one per spoken **segment** (a single speaker turn) — all sharing the same `calendarEventId`. There is no single "full transcript" object. To assemble a meeting's full transcript, list every segment for that meeting ordered by `startTime` and concatenate them:

```bash
curl -G "https://api.zero.inc/api/calendarEventTranscripts" \
  --data-urlencode 'where={"calendarEventId":"CALENDAR_EVENT_UUID"}' \
  --data-urlencode 'orderBy={"startTime":"asc"}' \
  -H "Authorization: Bearer YOUR_API_TOKEN"
```

A segment's `startTime`, `endTime`, and `duration` are **milliseconds from the start of the meeting**.

#### Finding a meeting

Transcript segments reference their meeting via `calendarEventId`. Use `GET /api/calendarEvents` to discover meetings (filter with `where` — e.g. by a `startTime` range, or by `contactIds`/`companyIds` using `$includes`), then query that meeting's transcript with the call above. Not every meeting has a transcript — only meetings recorded by a connected notetaker integration do.

## List meetings

> Returns meetings (calendar events) the user has access to. Filter by workspace using the \`where\` parameter: \`{"workspaceId": "\<WORKSPACE\_UUID>"}\`.\
> \
> Because \`contactIds\`, \`companyIds\`, and \`dealIds\` are arrays, filter by a linked record using the \`$includes\` operator — e.g. \`{"contactIds": {"$includes": "\<CONTACT\_UUID>"}}\`. Filter by date window with a \`startTime\` range, e.g. \`{"startTime": {"$gte": "2026-06-01T00:00:00Z", "$lt": "2026-07-01T00:00:00Z"}}\`.\
> \
> Only read access is exposed — meetings cannot be created, updated, or deleted via the API.<br>

````json
{"openapi":"3.0.3","info":{"title":"Zero API","version":"1.12.0"},"tags":[{"name":"Meetings","description":"Read meetings (calendar events) and their transcripts. Only read (`GET`) access is exposed via the API — meetings and transcripts cannot be created, updated, or deleted.\n\n### Transcripts are segment-grained\nA transcript is stored as many rows — one per spoken **segment** (a single speaker turn) — all sharing the same `calendarEventId`. There is no single \"full transcript\" object. To assemble a meeting's full transcript, list every segment for that meeting ordered by `startTime` and concatenate them:\n\n```bash\ncurl -G \"https://api.zero.inc/api/calendarEventTranscripts\" \\\n  --data-urlencode 'where={\"calendarEventId\":\"CALENDAR_EVENT_UUID\"}' \\\n  --data-urlencode 'orderBy={\"startTime\":\"asc\"}' \\\n  -H \"Authorization: Bearer YOUR_API_TOKEN\"\n```\n\nA segment's `startTime`, `endTime`, and `duration` are **milliseconds from the start of the meeting**.\n\n### Finding a meeting\nTranscript segments reference their meeting via `calendarEventId`. Use `GET /api/calendarEvents` to discover meetings (filter with `where` — e.g. by a `startTime` range, or by `contactIds`/`companyIds` using `$includes`), then query that meeting's transcript with the call above. Not every meeting has a transcript — only meetings recorded by a connected notetaker integration do.\n"}],"servers":[{"url":"https://api.zero.inc","description":"Production server"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"All API requests require a Bearer token in the Authorization header. Create an API key from [Workspace Settings → API keys](https://app.zero.inc/settings/workspace/api)"}},"parameters":{"fields":{"name":"fields","in":"query","description":"Comma-separated list of fields to return. Defaults to all fields.","schema":{"type":"string"}},"where":{"name":"where","in":"query","description":"JSON-encoded filter object. All top-level conditions are combined with AND logic. Use `$or` for OR logic.\n\nThe available operators depend on the **data type** of the field you are filtering on.\n\n---\n\n## String fields\nFields like `name`, `domain`, `description`, `linkedin`, `source`, `externalId`, `location`.\n\n| Operator | Description | Example |\n|----------|-------------|---------|\n| *(exact)* | Exact match | `{\"name\": \"Linear\"}` |\n| `$eq` | Explicit exact match | `{\"name\": {\"$eq\": \"Linear\"}}` |\n| `$not` | Not equal | `{\"source\": {\"$not\": \"import\"}}` |\n| `$in` | Matches any value in array | `{\"domain\": {\"$in\": [\"linear.app\", \"granola.so\"]}}` |\n| `$notIn` | Matches none of the values | `{\"source\": {\"$notIn\": [\"import\", \"api\"]}}` |\n| `$contains` | Case-insensitive word-boundary substring match | `{\"name\": {\"$contains\": \"YC\"}}` |\n| `$notContains` | Does not contain | `{\"name\": {\"$notContains\": \"Test\"}}` |\n| `$containsAny` | Contains any of the given strings | `{\"name\": {\"$containsAny\": [\"YC\", \"Techstars\"]}}` |\n| `$startsWith` | Starts with prefix | `{\"domain\": {\"$startsWith\": \"app.\"}}` |\n| `$endsWith` | Ends with suffix | `{\"email\": {\"$endsWith\": \"@zero.inc\"}}` |\n| `$exists` | Field is present and truthy | `{\"linkedin\": {\"$exists\": true}}` |\n| `$notExists` | Field is absent, null, or empty | `{\"linkedin\": {\"$notExists\": true}}` |\n\n---\n\n## Number fields\nFields like `value`, `confidence`.\n\n| Operator | Description | Example |\n|----------|-------------|---------|\n| *(exact)* | Exact match | `{\"value\": 5000}` |\n| `$eq` | Explicit exact match | `{\"value\": {\"$eq\": 5000}}` |\n| `$not` | Not equal | `{\"value\": {\"$not\": 0}}` |\n| `$gt` | Greater than | `{\"value\": {\"$gt\": 10000}}` |\n| `$gte` | Greater than or equal | `{\"value\": {\"$gte\": 5000}}` |\n| `$lt` | Less than | `{\"value\": {\"$lt\": 10000}}` |\n| `$lte` | Less than or equal | `{\"value\": {\"$lte\": 50000}}` |\n| `$in` | Matches any value in array | `{\"confidence\": {\"$in\": [0.25, 0.5, 0.75]}}` |\n| `$notIn` | Matches none of the values | `{\"confidence\": {\"$notIn\": [0, 1]}}` |\n| `$exists` | Field is present and truthy | `{\"value\": {\"$exists\": true}}` |\n| `$notExists` | Field is absent, null, or zero | `{\"value\": {\"$notExists\": true}}` |\n\nMultiple operators can be combined on one field:\n```json\n{\"value\": {\"$gte\": 5000, \"$lt\": 10000}}\n```\n\n---\n\n## Date fields\nFields like `closeDate`, `startDate`, `endDate`, `createdAt`, `updatedAt`.\n\nValues can be ISO 8601 strings (`\"2026-01-01\"`, `\"2026-01-01T00:00:00Z\"`) or **relative time macros**.\n\n**Relative time macros:** `+Nd` / `-Nd` (days), `+Nw` / `-Nw` (weeks), `+Nm` / `-Nm` (months), `+Ny` / `-Ny` (years), `+Nh` / `-Nh` (hours), `+Ns` / `-Ns` (seconds), `now()`.\n\n| Operator | Description | Example |\n|----------|-------------|---------|\n| `$gte` | On or after | `{\"closeDate\": {\"$gte\": \"2026-01-01\"}}` |\n| `$lte` | On or before | `{\"closeDate\": {\"$lte\": \"2026-03-31\"}}` |\n| `$gt` | After | `{\"createdAt\": {\"$gt\": \"2026-01-01T00:00:00Z\"}}` |\n| `$lt` | Before | `{\"createdAt\": {\"$lt\": \"now()\"}}` |\n| `$date` | Exact date match (compares date portion only) | `{\"closeDate\": {\"$date\": \"2026-01-15\"}}` |\n| `$exists` | Field is present and truthy | `{\"closeDate\": {\"$exists\": true}}` |\n| `$notExists` | Field is absent or null | `{\"closeDate\": {\"$notExists\": true}}` |\n\nDate range example:\n```json\n{\"closeDate\": {\"$gte\": \"2026-01-01\", \"$lte\": \"2026-03-31\"}}\n```\nRelative date example (closing in next 30 days):\n```json\n{\"closeDate\": {\"$gte\": \"now()\", \"$lte\": \"+30d\"}}\n```\n\n---\n\n## Array fields\nFields like `listIds`, `ownerIds`, `contactIds`.\n\n| Operator | Description | Example |\n|----------|-------------|---------|\n| `$includes` | Array contains the given value (use this — bare exact match is not supported) | `{\"listIds\": {\"$includes\": \"<LIST_UUID>\"}}` |\n| `$notIncludes` | Array does not contain the given value | `{\"ownerIds\": {\"$notIncludes\": \"<USER_UUID>\"}}` |\n| `$overlaps` | Array contains at least one of the given values | `{\"ownerIds\": {\"$overlaps\": [\"<UUID_1>\", \"<UUID_2>\"]}}` |\n| `$notOverlaps` | Array contains none of the given values | `{\"listIds\": {\"$notOverlaps\": [\"<UUID_1>\", \"<UUID_2>\"]}}` |\n| `$all` | Array contains all of the given values | `{\"listIds\": {\"$all\": [\"<UUID_1>\", \"<UUID_2>\"]}}` |\n| `$length` | Filter by array length (supports nested operators) | `{\"contactIds\": {\"$length\": {\"$gte\": 2}}}` |\n| `$exists` | Field is present and non-empty | `{\"ownerIds\": {\"$exists\": true}}` |\n| `$notExists` | Field is absent or empty | `{\"ownerIds\": {\"$notExists\": true}}` |\n\n---\n\n## UUID / ID fields\nFields like `id`, `workspaceId`, `companyId`, `stage`.\n\n| Operator | Description | Example |\n|----------|-------------|---------|\n| *(exact)* | Exact match | `{\"stage\": \"<PIPELINE_STAGE_UUID>\"}` |\n| `$in` | Matches any value in array | `{\"stage\": {\"$in\": [\"<UUID_1>\", \"<UUID_2>\"]}}` |\n| `$notIn` | Matches none of the values | `{\"stage\": {\"$notIn\": [\"<UUID_1>\"]}}` |\n| `$not` | Not equal | `{\"stage\": {\"$not\": \"<UUID>\"}}` |\n\n---\n\n## Boolean fields\nFields like `archived`.\n\n| Operator | Description | Example |\n|----------|-------------|---------|\n| *(exact)* | Exact match | `{\"archived\": false}` |\n| `$not` | Not equal | `{\"archived\": {\"$not\": true}}` |\n\n---\n\n## Logical operators\nThese work across all data types.\n\n`$or` — matches if **any** sub-condition is true:\n```json\n{\n  \"workspaceId\": \"<WORKSPACE_UUID>\",\n  \"$or\": [\n    {\"ownerIds\": {\"$overlaps\": [\"<USER_UUID_1>\", \"<USER_UUID_2>\"]}},\n    {\"closeDate\": {\"$gte\": \"2026-01-01\"}}\n  ]\n}\n```\n\n`$and` — matches if **all** sub-conditions are true (useful when you need multiple conditions on the same field):\n```json\n{\n  \"$and\": [\n    {\"name\": {\"$contains\": \"Enterprise\"}},\n    {\"name\": {\"$notContains\": \"Test\"}}\n  ]\n}\n```\n\n---\n\n## Dot-notation (relation filtering)\nUse dot-syntax to filter records based on properties of related objects:\n```json\n{\"company.name\": \"Linear\"}\n{\"company.domain\": {\"$in\": [\"linear.app\", \"granola.so\"]}}\n{\"company.location.city\": \"San Francisco\"}\n{\"companyProfile.categories\": {\"$overlaps\": [\"Sales\", \"Marketing\"]}}\n```\nAll operators available for the target field's data type can be used with dot-notation.\n\n---\n\n## Custom property filtering\nCustom properties are stored in the `custom` object on records, keyed by UUID. Use `GET /api/columns` to discover the available custom property IDs, types, and options for a workspace.\n\nFilter on custom properties using `custom.<COLUMN_ID>` with operators appropriate for the column's type.\n\n> **Note:** For `select` and `multiselect` columns, option values are UUIDs (the `key` field from the column's `options` array). Use the UUID, not the human-readable name.\n\n```json\n// Text custom property\n{\"custom.54e1ca7d-69c3-4b77-8266-8085b5834116\": {\"$contains\": \"enterprise\"}}\n\n// Select custom property (use the option key UUID)\n{\"custom.a1b2c3d4-e5f6-7890-abcd-ef1234567890\": \"3e839b5c-b311-4887-b2da-727d2d75cdd6\"}\n\n// Multi-select custom property (use option key UUIDs)\n{\"custom.b2c3d4e5-f6a7-8901-bcde-f12345678901\": {\"$overlaps\": [\"a1b1c1d1-e1f1-1111-aaaa-111111111111\", \"b2b2c2d2-e2f2-2222-bbbb-222222222222\"]}}\n\n// Currency/number custom property\n{\"custom.c3d4e5f6-a7b8-9012-cdef-123456789012\": {\"$gte\": 100000}}\n\n// Date custom property\n{\"custom.d4e5f6a7-b8c9-0123-defa-234567890123\": {\"$gte\": \"2026-01-01\"}}\n\n// Boolean custom property\n{\"custom.e5f6a7b8-c9d0-1234-efab-345678901234\": true}\n\n// Check if custom property has a value\n{\"custom.f6a7b8c9-d0e1-2345-fabc-456789012345\": {\"$exists\": true}}\n```\n\n---\n\n## Complex example\nAll top-level keys are ANDed together:\n```json\n{\n  \"name\": {\"$contains\": \"Zero\"},\n  \"location.city\": \"Helsinki\",\n  \"location.country\": {\"$in\": [\"United Kingdom\", \"Germany\", \"Sweden\"]},\n  \"value\": {\"$gte\": 10000},\n  \"closeDate\": {\"$gte\": \"2026-01-01\", \"$lte\": \"2026-03-31\"},\n  \"ownerIds\": {\"$includes\": \"<USER_UUID>\"},\n  \"stage\": {\"$in\": [\"<UUID_1>\", \"<UUID_2>\"]},\n  \"lastActivity\": {\"$exists\": true},\n  \"companyProfile.categories\": {\"$overlaps\": [\"Sales\", \"Marketing\"]},\n  \"custom.54e1ca7d-69c3-4b77-8266-8085b5834116\": {\"$contains\": \"enterprise\"}\n}\n```\n","schema":{"type":"string"}},"limit":{"name":"limit","in":"query","description":"Maximum number of records to return","schema":{"type":"integer","default":100}},"offset":{"name":"offset","in":"query","description":"Pagination offset","schema":{"type":"integer","default":0}},"orderBy":{"name":"orderBy","in":"query","description":"JSON string for sort order","schema":{"type":"string"}}},"schemas":{"CalendarEvent":{"type":"object","description":"A meeting (calendar event). Meetings recorded by a connected notetaker integration also have transcript segments, retrievable via `GET /api/calendarEventTranscripts` filtered by `calendarEventId`.\n\nOnly a curated, read-only subset of meeting fields is exposed via the API.\n","properties":{"id":{"type":"string","format":"uuid"},"workspaceId":{"type":"string","format":"uuid"},"name":{"type":"string","nullable":true,"description":"Title of the meeting."},"emoji":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"location":{"type":"string","nullable":true},"meetingLink":{"type":"string","nullable":true,"description":"Video conferencing link (e.g. Google Meet, Zoom)."},"startTime":{"type":"string","format":"date-time","nullable":true,"description":"Start of the meeting. Null for all-day events, which use `startDate`/`endDate` instead."},"endTime":{"type":"string","format":"date-time","nullable":true,"description":"End of the meeting."},"startDate":{"type":"string","format":"date","nullable":true,"description":"Start date for all-day events."},"endDate":{"type":"string","format":"date","nullable":true,"description":"End date for all-day events."},"busy":{"type":"boolean","description":"Whether the meeting marks attendees as busy."},"organizer":{"type":"object","nullable":true,"description":"The meeting organizer, as provided by the calendar source. May include additional provider-specific fields.","properties":{"email":{"type":"string","nullable":true},"displayName":{"type":"string","nullable":true,"description":"Display name of the organizer."}}},"attendeeEmails":{"type":"array","nullable":true,"items":{"type":"string"},"description":"Email addresses of the meeting attendees."},"summary":{"type":"object","nullable":true,"description":"AI-generated meeting summary in [Tiptap](https://tiptap.dev/) document format (a JSON object with a `type: \"doc\"` root). Null when no summary has been generated.\n"},"userIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Zero users associated with the meeting."},"calendarIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Calendars the meeting belongs to."},"companyIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Companies linked to the meeting."},"contactIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Contacts linked to the meeting."},"dealIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Deals linked to the meeting."},"external":{"type":"boolean","description":"Whether the meeting originated from an external calendar sync."},"externalNotetakerUrl":{"type":"string","nullable":true,"description":"Link to the meeting in the external notetaker (e.g. Circleback)."},"audioUrl":{"type":"string","nullable":true,"description":"URL to the meeting audio recording, if available."},"videoUrl":{"type":"string","nullable":true,"description":"URL to the meeting video recording, if available."},"archived":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}},"responses":{"Unauthorized":{"description":"Authentication failed or token is invalid/expired","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}}}},"paths":{"/api/calendarEvents":{"get":{"tags":["Meetings"],"summary":"List meetings","description":"Returns meetings (calendar events) the user has access to. Filter by workspace using the `where` parameter: `{\"workspaceId\": \"<WORKSPACE_UUID>\"}`.\n\nBecause `contactIds`, `companyIds`, and `dealIds` are arrays, filter by a linked record using the `$includes` operator — e.g. `{\"contactIds\": {\"$includes\": \"<CONTACT_UUID>\"}}`. Filter by date window with a `startTime` range, e.g. `{\"startTime\": {\"$gte\": \"2026-06-01T00:00:00Z\", \"$lt\": \"2026-07-01T00:00:00Z\"}}`.\n\nOnly read access is exposed — meetings cannot be created, updated, or deleted via the API.\n","operationId":"listCalendarEvents","parameters":[{"$ref":"#/components/parameters/fields"},{"$ref":"#/components/parameters/where"},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"},{"$ref":"#/components/parameters/orderBy"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CalendarEvent"}},"total":{"type":"integer"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}}}}
````

## Get a meeting

> Retrieve a single meeting (calendar event) by ID.

````json
{"openapi":"3.0.3","info":{"title":"Zero API","version":"1.12.0"},"tags":[{"name":"Meetings","description":"Read meetings (calendar events) and their transcripts. Only read (`GET`) access is exposed via the API — meetings and transcripts cannot be created, updated, or deleted.\n\n### Transcripts are segment-grained\nA transcript is stored as many rows — one per spoken **segment** (a single speaker turn) — all sharing the same `calendarEventId`. There is no single \"full transcript\" object. To assemble a meeting's full transcript, list every segment for that meeting ordered by `startTime` and concatenate them:\n\n```bash\ncurl -G \"https://api.zero.inc/api/calendarEventTranscripts\" \\\n  --data-urlencode 'where={\"calendarEventId\":\"CALENDAR_EVENT_UUID\"}' \\\n  --data-urlencode 'orderBy={\"startTime\":\"asc\"}' \\\n  -H \"Authorization: Bearer YOUR_API_TOKEN\"\n```\n\nA segment's `startTime`, `endTime`, and `duration` are **milliseconds from the start of the meeting**.\n\n### Finding a meeting\nTranscript segments reference their meeting via `calendarEventId`. Use `GET /api/calendarEvents` to discover meetings (filter with `where` — e.g. by a `startTime` range, or by `contactIds`/`companyIds` using `$includes`), then query that meeting's transcript with the call above. Not every meeting has a transcript — only meetings recorded by a connected notetaker integration do.\n"}],"servers":[{"url":"https://api.zero.inc","description":"Production server"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"All API requests require a Bearer token in the Authorization header. Create an API key from [Workspace Settings → API keys](https://app.zero.inc/settings/workspace/api)"}},"schemas":{"CalendarEvent":{"type":"object","description":"A meeting (calendar event). Meetings recorded by a connected notetaker integration also have transcript segments, retrievable via `GET /api/calendarEventTranscripts` filtered by `calendarEventId`.\n\nOnly a curated, read-only subset of meeting fields is exposed via the API.\n","properties":{"id":{"type":"string","format":"uuid"},"workspaceId":{"type":"string","format":"uuid"},"name":{"type":"string","nullable":true,"description":"Title of the meeting."},"emoji":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"location":{"type":"string","nullable":true},"meetingLink":{"type":"string","nullable":true,"description":"Video conferencing link (e.g. Google Meet, Zoom)."},"startTime":{"type":"string","format":"date-time","nullable":true,"description":"Start of the meeting. Null for all-day events, which use `startDate`/`endDate` instead."},"endTime":{"type":"string","format":"date-time","nullable":true,"description":"End of the meeting."},"startDate":{"type":"string","format":"date","nullable":true,"description":"Start date for all-day events."},"endDate":{"type":"string","format":"date","nullable":true,"description":"End date for all-day events."},"busy":{"type":"boolean","description":"Whether the meeting marks attendees as busy."},"organizer":{"type":"object","nullable":true,"description":"The meeting organizer, as provided by the calendar source. May include additional provider-specific fields.","properties":{"email":{"type":"string","nullable":true},"displayName":{"type":"string","nullable":true,"description":"Display name of the organizer."}}},"attendeeEmails":{"type":"array","nullable":true,"items":{"type":"string"},"description":"Email addresses of the meeting attendees."},"summary":{"type":"object","nullable":true,"description":"AI-generated meeting summary in [Tiptap](https://tiptap.dev/) document format (a JSON object with a `type: \"doc\"` root). Null when no summary has been generated.\n"},"userIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Zero users associated with the meeting."},"calendarIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Calendars the meeting belongs to."},"companyIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Companies linked to the meeting."},"contactIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Contacts linked to the meeting."},"dealIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Deals linked to the meeting."},"external":{"type":"boolean","description":"Whether the meeting originated from an external calendar sync."},"externalNotetakerUrl":{"type":"string","nullable":true,"description":"Link to the meeting in the external notetaker (e.g. Circleback)."},"audioUrl":{"type":"string","nullable":true,"description":"URL to the meeting audio recording, if available."},"videoUrl":{"type":"string","nullable":true,"description":"URL to the meeting video recording, if available."},"archived":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}},"responses":{"Unauthorized":{"description":"Authentication failed or token is invalid/expired","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}}}},"paths":{"/api/calendarEvents/{calendarEventId}":{"get":{"tags":["Meetings"],"summary":"Get a meeting","description":"Retrieve a single meeting (calendar event) by ID.","operationId":"getCalendarEvent","parameters":[{"name":"calendarEventId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/CalendarEvent"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}}}}
````

## List transcript segments

> Returns meeting transcript segments the user has access to. \*\*Each row is a single transcript segment\*\* (one speaker turn), so a meeting's full transcript spans many rows that share the same \`calendarEventId\`.\
> \
> Filter to one meeting with the \`where\` parameter and order by \`startTime\` to reconstruct the conversation in order:\
> \
> \`\`\`bash\
> curl -G "<https://api.zero.inc/api/calendarEventTranscripts>" \\\
> &#x20; \--data-urlencode 'where={"calendarEventId":"CALENDAR\_EVENT\_UUID"}' \\\
> &#x20; \--data-urlencode 'orderBy={"startTime":"asc"}' \\\
> &#x20; -H "Authorization: Bearer YOUR\_API\_TOKEN"\
> \`\`\`\
> \
> A segment's \`startTime\`, \`endTime\`, and \`duration\` are milliseconds from the start of the meeting. Only read access is exposed — transcripts cannot be created, updated, or deleted via the API.<br>

````json
{"openapi":"3.0.3","info":{"title":"Zero API","version":"1.12.0"},"tags":[{"name":"Meetings","description":"Read meetings (calendar events) and their transcripts. Only read (`GET`) access is exposed via the API — meetings and transcripts cannot be created, updated, or deleted.\n\n### Transcripts are segment-grained\nA transcript is stored as many rows — one per spoken **segment** (a single speaker turn) — all sharing the same `calendarEventId`. There is no single \"full transcript\" object. To assemble a meeting's full transcript, list every segment for that meeting ordered by `startTime` and concatenate them:\n\n```bash\ncurl -G \"https://api.zero.inc/api/calendarEventTranscripts\" \\\n  --data-urlencode 'where={\"calendarEventId\":\"CALENDAR_EVENT_UUID\"}' \\\n  --data-urlencode 'orderBy={\"startTime\":\"asc\"}' \\\n  -H \"Authorization: Bearer YOUR_API_TOKEN\"\n```\n\nA segment's `startTime`, `endTime`, and `duration` are **milliseconds from the start of the meeting**.\n\n### Finding a meeting\nTranscript segments reference their meeting via `calendarEventId`. Use `GET /api/calendarEvents` to discover meetings (filter with `where` — e.g. by a `startTime` range, or by `contactIds`/`companyIds` using `$includes`), then query that meeting's transcript with the call above. Not every meeting has a transcript — only meetings recorded by a connected notetaker integration do.\n"}],"servers":[{"url":"https://api.zero.inc","description":"Production server"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"All API requests require a Bearer token in the Authorization header. Create an API key from [Workspace Settings → API keys](https://app.zero.inc/settings/workspace/api)"}},"parameters":{"fields":{"name":"fields","in":"query","description":"Comma-separated list of fields to return. Defaults to all fields.","schema":{"type":"string"}},"where":{"name":"where","in":"query","description":"JSON-encoded filter object. All top-level conditions are combined with AND logic. Use `$or` for OR logic.\n\nThe available operators depend on the **data type** of the field you are filtering on.\n\n---\n\n## String fields\nFields like `name`, `domain`, `description`, `linkedin`, `source`, `externalId`, `location`.\n\n| Operator | Description | Example |\n|----------|-------------|---------|\n| *(exact)* | Exact match | `{\"name\": \"Linear\"}` |\n| `$eq` | Explicit exact match | `{\"name\": {\"$eq\": \"Linear\"}}` |\n| `$not` | Not equal | `{\"source\": {\"$not\": \"import\"}}` |\n| `$in` | Matches any value in array | `{\"domain\": {\"$in\": [\"linear.app\", \"granola.so\"]}}` |\n| `$notIn` | Matches none of the values | `{\"source\": {\"$notIn\": [\"import\", \"api\"]}}` |\n| `$contains` | Case-insensitive word-boundary substring match | `{\"name\": {\"$contains\": \"YC\"}}` |\n| `$notContains` | Does not contain | `{\"name\": {\"$notContains\": \"Test\"}}` |\n| `$containsAny` | Contains any of the given strings | `{\"name\": {\"$containsAny\": [\"YC\", \"Techstars\"]}}` |\n| `$startsWith` | Starts with prefix | `{\"domain\": {\"$startsWith\": \"app.\"}}` |\n| `$endsWith` | Ends with suffix | `{\"email\": {\"$endsWith\": \"@zero.inc\"}}` |\n| `$exists` | Field is present and truthy | `{\"linkedin\": {\"$exists\": true}}` |\n| `$notExists` | Field is absent, null, or empty | `{\"linkedin\": {\"$notExists\": true}}` |\n\n---\n\n## Number fields\nFields like `value`, `confidence`.\n\n| Operator | Description | Example |\n|----------|-------------|---------|\n| *(exact)* | Exact match | `{\"value\": 5000}` |\n| `$eq` | Explicit exact match | `{\"value\": {\"$eq\": 5000}}` |\n| `$not` | Not equal | `{\"value\": {\"$not\": 0}}` |\n| `$gt` | Greater than | `{\"value\": {\"$gt\": 10000}}` |\n| `$gte` | Greater than or equal | `{\"value\": {\"$gte\": 5000}}` |\n| `$lt` | Less than | `{\"value\": {\"$lt\": 10000}}` |\n| `$lte` | Less than or equal | `{\"value\": {\"$lte\": 50000}}` |\n| `$in` | Matches any value in array | `{\"confidence\": {\"$in\": [0.25, 0.5, 0.75]}}` |\n| `$notIn` | Matches none of the values | `{\"confidence\": {\"$notIn\": [0, 1]}}` |\n| `$exists` | Field is present and truthy | `{\"value\": {\"$exists\": true}}` |\n| `$notExists` | Field is absent, null, or zero | `{\"value\": {\"$notExists\": true}}` |\n\nMultiple operators can be combined on one field:\n```json\n{\"value\": {\"$gte\": 5000, \"$lt\": 10000}}\n```\n\n---\n\n## Date fields\nFields like `closeDate`, `startDate`, `endDate`, `createdAt`, `updatedAt`.\n\nValues can be ISO 8601 strings (`\"2026-01-01\"`, `\"2026-01-01T00:00:00Z\"`) or **relative time macros**.\n\n**Relative time macros:** `+Nd` / `-Nd` (days), `+Nw` / `-Nw` (weeks), `+Nm` / `-Nm` (months), `+Ny` / `-Ny` (years), `+Nh` / `-Nh` (hours), `+Ns` / `-Ns` (seconds), `now()`.\n\n| Operator | Description | Example |\n|----------|-------------|---------|\n| `$gte` | On or after | `{\"closeDate\": {\"$gte\": \"2026-01-01\"}}` |\n| `$lte` | On or before | `{\"closeDate\": {\"$lte\": \"2026-03-31\"}}` |\n| `$gt` | After | `{\"createdAt\": {\"$gt\": \"2026-01-01T00:00:00Z\"}}` |\n| `$lt` | Before | `{\"createdAt\": {\"$lt\": \"now()\"}}` |\n| `$date` | Exact date match (compares date portion only) | `{\"closeDate\": {\"$date\": \"2026-01-15\"}}` |\n| `$exists` | Field is present and truthy | `{\"closeDate\": {\"$exists\": true}}` |\n| `$notExists` | Field is absent or null | `{\"closeDate\": {\"$notExists\": true}}` |\n\nDate range example:\n```json\n{\"closeDate\": {\"$gte\": \"2026-01-01\", \"$lte\": \"2026-03-31\"}}\n```\nRelative date example (closing in next 30 days):\n```json\n{\"closeDate\": {\"$gte\": \"now()\", \"$lte\": \"+30d\"}}\n```\n\n---\n\n## Array fields\nFields like `listIds`, `ownerIds`, `contactIds`.\n\n| Operator | Description | Example |\n|----------|-------------|---------|\n| `$includes` | Array contains the given value (use this — bare exact match is not supported) | `{\"listIds\": {\"$includes\": \"<LIST_UUID>\"}}` |\n| `$notIncludes` | Array does not contain the given value | `{\"ownerIds\": {\"$notIncludes\": \"<USER_UUID>\"}}` |\n| `$overlaps` | Array contains at least one of the given values | `{\"ownerIds\": {\"$overlaps\": [\"<UUID_1>\", \"<UUID_2>\"]}}` |\n| `$notOverlaps` | Array contains none of the given values | `{\"listIds\": {\"$notOverlaps\": [\"<UUID_1>\", \"<UUID_2>\"]}}` |\n| `$all` | Array contains all of the given values | `{\"listIds\": {\"$all\": [\"<UUID_1>\", \"<UUID_2>\"]}}` |\n| `$length` | Filter by array length (supports nested operators) | `{\"contactIds\": {\"$length\": {\"$gte\": 2}}}` |\n| `$exists` | Field is present and non-empty | `{\"ownerIds\": {\"$exists\": true}}` |\n| `$notExists` | Field is absent or empty | `{\"ownerIds\": {\"$notExists\": true}}` |\n\n---\n\n## UUID / ID fields\nFields like `id`, `workspaceId`, `companyId`, `stage`.\n\n| Operator | Description | Example |\n|----------|-------------|---------|\n| *(exact)* | Exact match | `{\"stage\": \"<PIPELINE_STAGE_UUID>\"}` |\n| `$in` | Matches any value in array | `{\"stage\": {\"$in\": [\"<UUID_1>\", \"<UUID_2>\"]}}` |\n| `$notIn` | Matches none of the values | `{\"stage\": {\"$notIn\": [\"<UUID_1>\"]}}` |\n| `$not` | Not equal | `{\"stage\": {\"$not\": \"<UUID>\"}}` |\n\n---\n\n## Boolean fields\nFields like `archived`.\n\n| Operator | Description | Example |\n|----------|-------------|---------|\n| *(exact)* | Exact match | `{\"archived\": false}` |\n| `$not` | Not equal | `{\"archived\": {\"$not\": true}}` |\n\n---\n\n## Logical operators\nThese work across all data types.\n\n`$or` — matches if **any** sub-condition is true:\n```json\n{\n  \"workspaceId\": \"<WORKSPACE_UUID>\",\n  \"$or\": [\n    {\"ownerIds\": {\"$overlaps\": [\"<USER_UUID_1>\", \"<USER_UUID_2>\"]}},\n    {\"closeDate\": {\"$gte\": \"2026-01-01\"}}\n  ]\n}\n```\n\n`$and` — matches if **all** sub-conditions are true (useful when you need multiple conditions on the same field):\n```json\n{\n  \"$and\": [\n    {\"name\": {\"$contains\": \"Enterprise\"}},\n    {\"name\": {\"$notContains\": \"Test\"}}\n  ]\n}\n```\n\n---\n\n## Dot-notation (relation filtering)\nUse dot-syntax to filter records based on properties of related objects:\n```json\n{\"company.name\": \"Linear\"}\n{\"company.domain\": {\"$in\": [\"linear.app\", \"granola.so\"]}}\n{\"company.location.city\": \"San Francisco\"}\n{\"companyProfile.categories\": {\"$overlaps\": [\"Sales\", \"Marketing\"]}}\n```\nAll operators available for the target field's data type can be used with dot-notation.\n\n---\n\n## Custom property filtering\nCustom properties are stored in the `custom` object on records, keyed by UUID. Use `GET /api/columns` to discover the available custom property IDs, types, and options for a workspace.\n\nFilter on custom properties using `custom.<COLUMN_ID>` with operators appropriate for the column's type.\n\n> **Note:** For `select` and `multiselect` columns, option values are UUIDs (the `key` field from the column's `options` array). Use the UUID, not the human-readable name.\n\n```json\n// Text custom property\n{\"custom.54e1ca7d-69c3-4b77-8266-8085b5834116\": {\"$contains\": \"enterprise\"}}\n\n// Select custom property (use the option key UUID)\n{\"custom.a1b2c3d4-e5f6-7890-abcd-ef1234567890\": \"3e839b5c-b311-4887-b2da-727d2d75cdd6\"}\n\n// Multi-select custom property (use option key UUIDs)\n{\"custom.b2c3d4e5-f6a7-8901-bcde-f12345678901\": {\"$overlaps\": [\"a1b1c1d1-e1f1-1111-aaaa-111111111111\", \"b2b2c2d2-e2f2-2222-bbbb-222222222222\"]}}\n\n// Currency/number custom property\n{\"custom.c3d4e5f6-a7b8-9012-cdef-123456789012\": {\"$gte\": 100000}}\n\n// Date custom property\n{\"custom.d4e5f6a7-b8c9-0123-defa-234567890123\": {\"$gte\": \"2026-01-01\"}}\n\n// Boolean custom property\n{\"custom.e5f6a7b8-c9d0-1234-efab-345678901234\": true}\n\n// Check if custom property has a value\n{\"custom.f6a7b8c9-d0e1-2345-fabc-456789012345\": {\"$exists\": true}}\n```\n\n---\n\n## Complex example\nAll top-level keys are ANDed together:\n```json\n{\n  \"name\": {\"$contains\": \"Zero\"},\n  \"location.city\": \"Helsinki\",\n  \"location.country\": {\"$in\": [\"United Kingdom\", \"Germany\", \"Sweden\"]},\n  \"value\": {\"$gte\": 10000},\n  \"closeDate\": {\"$gte\": \"2026-01-01\", \"$lte\": \"2026-03-31\"},\n  \"ownerIds\": {\"$includes\": \"<USER_UUID>\"},\n  \"stage\": {\"$in\": [\"<UUID_1>\", \"<UUID_2>\"]},\n  \"lastActivity\": {\"$exists\": true},\n  \"companyProfile.categories\": {\"$overlaps\": [\"Sales\", \"Marketing\"]},\n  \"custom.54e1ca7d-69c3-4b77-8266-8085b5834116\": {\"$contains\": \"enterprise\"}\n}\n```\n","schema":{"type":"string"}},"limit":{"name":"limit","in":"query","description":"Maximum number of records to return","schema":{"type":"integer","default":100}},"offset":{"name":"offset","in":"query","description":"Pagination offset","schema":{"type":"integer","default":0}},"orderBy":{"name":"orderBy","in":"query","description":"JSON string for sort order","schema":{"type":"string"}}},"schemas":{"Transcript":{"type":"object","description":"A single transcript segment (one speaker turn) from a recorded meeting. A meeting's full transcript is made up of many segments that share the same `calendarEventId`, ordered by `startTime`.\n","properties":{"id":{"type":"string","format":"uuid"},"workspaceId":{"type":"string","format":"uuid"},"calendarEventId":{"type":"string","format":"uuid","description":"The meeting (calendar event) this segment belongs to."},"integrationId":{"type":"string","format":"uuid","nullable":true,"description":"The notetaker integration that produced this segment."},"speaker":{"type":"string","nullable":true,"description":"Name of the speaker for this segment (e.g. \"Jane Doe\"), or \"Unknown\"."},"content":{"type":"string","nullable":true,"description":"The spoken text of this segment."},"startTime":{"type":"integer","nullable":true,"description":"Start offset of this segment, in milliseconds from the start of the meeting."},"endTime":{"type":"integer","nullable":true,"description":"End offset of this segment, in milliseconds from the start of the meeting."},"duration":{"type":"integer","nullable":true,"description":"Length of this segment in milliseconds (`endTime` − `startTime`)."},"topic":{"type":"string","nullable":true,"description":"Optional topic label for the segment. Often empty."},"sentiment":{"type":"string","nullable":true,"description":"Optional sentiment label for the segment. Often empty."},"archived":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"createdById":{"type":"string","format":"uuid","nullable":true},"updatedById":{"type":"string","format":"uuid","nullable":true}}}},"responses":{"Unauthorized":{"description":"Authentication failed or token is invalid/expired","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}}}},"paths":{"/api/calendarEventTranscripts":{"get":{"tags":["Meetings"],"summary":"List transcript segments","description":"Returns meeting transcript segments the user has access to. **Each row is a single transcript segment** (one speaker turn), so a meeting's full transcript spans many rows that share the same `calendarEventId`.\n\nFilter to one meeting with the `where` parameter and order by `startTime` to reconstruct the conversation in order:\n\n```bash\ncurl -G \"https://api.zero.inc/api/calendarEventTranscripts\" \\\n  --data-urlencode 'where={\"calendarEventId\":\"CALENDAR_EVENT_UUID\"}' \\\n  --data-urlencode 'orderBy={\"startTime\":\"asc\"}' \\\n  -H \"Authorization: Bearer YOUR_API_TOKEN\"\n```\n\nA segment's `startTime`, `endTime`, and `duration` are milliseconds from the start of the meeting. Only read access is exposed — transcripts cannot be created, updated, or deleted via the API.\n","operationId":"listCalendarEventTranscripts","parameters":[{"$ref":"#/components/parameters/fields"},{"$ref":"#/components/parameters/where"},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"},{"$ref":"#/components/parameters/orderBy"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Transcript"}},"total":{"type":"integer"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}}}}
````

## Get a transcript segment

> Retrieve a single transcript segment by ID. A segment is one speaker turn — not a meeting's full transcript. To get the full transcript, list segments filtered by \`calendarEventId\` (see \*\*List transcript segments\*\*).<br>

````json
{"openapi":"3.0.3","info":{"title":"Zero API","version":"1.12.0"},"tags":[{"name":"Meetings","description":"Read meetings (calendar events) and their transcripts. Only read (`GET`) access is exposed via the API — meetings and transcripts cannot be created, updated, or deleted.\n\n### Transcripts are segment-grained\nA transcript is stored as many rows — one per spoken **segment** (a single speaker turn) — all sharing the same `calendarEventId`. There is no single \"full transcript\" object. To assemble a meeting's full transcript, list every segment for that meeting ordered by `startTime` and concatenate them:\n\n```bash\ncurl -G \"https://api.zero.inc/api/calendarEventTranscripts\" \\\n  --data-urlencode 'where={\"calendarEventId\":\"CALENDAR_EVENT_UUID\"}' \\\n  --data-urlencode 'orderBy={\"startTime\":\"asc\"}' \\\n  -H \"Authorization: Bearer YOUR_API_TOKEN\"\n```\n\nA segment's `startTime`, `endTime`, and `duration` are **milliseconds from the start of the meeting**.\n\n### Finding a meeting\nTranscript segments reference their meeting via `calendarEventId`. Use `GET /api/calendarEvents` to discover meetings (filter with `where` — e.g. by a `startTime` range, or by `contactIds`/`companyIds` using `$includes`), then query that meeting's transcript with the call above. Not every meeting has a transcript — only meetings recorded by a connected notetaker integration do.\n"}],"servers":[{"url":"https://api.zero.inc","description":"Production server"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"All API requests require a Bearer token in the Authorization header. Create an API key from [Workspace Settings → API keys](https://app.zero.inc/settings/workspace/api)"}},"schemas":{"Transcript":{"type":"object","description":"A single transcript segment (one speaker turn) from a recorded meeting. A meeting's full transcript is made up of many segments that share the same `calendarEventId`, ordered by `startTime`.\n","properties":{"id":{"type":"string","format":"uuid"},"workspaceId":{"type":"string","format":"uuid"},"calendarEventId":{"type":"string","format":"uuid","description":"The meeting (calendar event) this segment belongs to."},"integrationId":{"type":"string","format":"uuid","nullable":true,"description":"The notetaker integration that produced this segment."},"speaker":{"type":"string","nullable":true,"description":"Name of the speaker for this segment (e.g. \"Jane Doe\"), or \"Unknown\"."},"content":{"type":"string","nullable":true,"description":"The spoken text of this segment."},"startTime":{"type":"integer","nullable":true,"description":"Start offset of this segment, in milliseconds from the start of the meeting."},"endTime":{"type":"integer","nullable":true,"description":"End offset of this segment, in milliseconds from the start of the meeting."},"duration":{"type":"integer","nullable":true,"description":"Length of this segment in milliseconds (`endTime` − `startTime`)."},"topic":{"type":"string","nullable":true,"description":"Optional topic label for the segment. Often empty."},"sentiment":{"type":"string","nullable":true,"description":"Optional sentiment label for the segment. Often empty."},"archived":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"createdById":{"type":"string","format":"uuid","nullable":true},"updatedById":{"type":"string","format":"uuid","nullable":true}}}},"responses":{"Unauthorized":{"description":"Authentication failed or token is invalid/expired","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}}}},"paths":{"/api/calendarEventTranscripts/{transcriptId}":{"get":{"tags":["Meetings"],"summary":"Get a transcript segment","description":"Retrieve a single transcript segment by ID. A segment is one speaker turn — not a meeting's full transcript. To get the full transcript, list segments filtered by `calendarEventId` (see **List transcript segments**).\n","operationId":"getCalendarEventTranscript","parameters":[{"name":"transcriptId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Transcript"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}}}}
````


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.zero.inc/features/api/meetings.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
