Appearance
List meetings
GET /api/v1/meetings meetings:read
Meetings of the workspace. Every filter is applied on the server — you do not have to (and are not meant to) fetch everything and filter afterwards.
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
limit | integer | — | Between 1 and 100. Default 50. |
offset | integer | — | At least 0. Default 0. |
status | string | — | Values: scheduled, live, processing, ready, failed, no_bot, no_speech. |
source | string | — | Values: calendar, url, upload. |
platform | string | — | Values: teams, meet, zoom, upload. |
from | string | — | Only meetings that start at or after this point in time (ISO 8601, for example 2026-08-01 or 2026-08-01T09:00:00Z). Meetings without a start time — an upload — fall out of any range filter. An invalid value gives 400. |
to | string | — | Only meetings that start at or before this point in time (ISO 8601). |
q | string | — | Substring of the title, ignoring upper and lower case. |
customer | string | — | Company domain, for example company.example. /customers lists the valid values. |
order | string | — | Sort order. created_at and starts_at descending, title ascending. Values: created_at, starts_at, title. Default created_at. |
Response 200
A list of meetings. pagination carries the clamped request values.
Example response
json
{
"data": [
{
"id": "e07b6d13-84af-4c92-b5d7-0a9e1f83c246",
"title": "Quarterly review",
"platform": "teams",
"source": "calendar",
"status": "ready",
"starts_at": "2026-08-04T08:00:00Z",
"ends_at": "2026-08-04T09:00:00Z",
"created_at": "2026-08-01T09:12:44Z"
}
],
"pagination": {
"limit": 50,
"offset": 0,
"total": 3
}
}| Field | Type | Required | Description |
|---|---|---|---|
data | object[] | yes | The meetings on this page. |
data[].id | uuid | yes | Identifies the meeting everywhere in this API. |
data[].title | string | yes | Subject, as the calendar or the upload spelled it. |
data[].platform | string | yes | Where it took place. upload means there was no live meeting — a recording came in. Values: teams, meet, zoom, upload. |
data[].source | string | yes | How the meeting reached Protoki. Values: calendar, url, upload. |
data[].status | string | yes | Where it stands. Only ready promises minutes; no_speech means nobody said anything worth writing down, and no_bot that no recorder ever joined. Values: scheduled, live, processing, ready, failed, no_bot, no_speech. |
data[].starts_at | date-time | null | — | Start of the appointment. null for an upload, which has none. |
data[].ends_at | date-time | null | — | End of the appointment. null for an upload. |
data[].created_at | date-time | yes | When the meeting was first recorded in Protoki. |
pagination | object | yes | Where this page sits in the whole set. |
pagination.limit | integer | yes | The page size that was applied, after clamping. |
pagination.offset | integer | yes | The offset that was applied. |
pagination.total | integer | yes | Number of hits in total, ignoring limit and offset. |
Other answers
| Code | Meaning |
|---|---|
400 | Invalid parameter — the text names the field and the shape expected. |
401 | No key, or a key that is not valid. |
403 | The key is missing the scope this endpoint needs. |
503 | The endpoint does not exist on this deployment yet, because a database change has not been applied. A temporary state, not a mistake in your request. |