# List meetings

`GET /meeting.list`

## Description

List meetings, ordered newest-first.

**Access:** Organization and Personal. Personal tokens return meetings the
authenticated user participated in. Organization tokens return every meeting
in the Roam only with [`admin:meetings:read`](/docs/guides/scopes#meeting-width-adminmeetingsread);
without it, results are limited to meetings the install's bot has access to.

**Required scope:** `meetings:read` (add `admin:meetings:read` for roam-wide org access)

---

**OpenAPI Spec:** [chat-v1.json](https://developer.ro.am/chat-v1.json)

## Authentication

```
Authorization: Bearer YOUR_API_KEY
```

## Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `before` | query | string | No | Only return meetings that started before this time (RFC-3339). Sub-millisecond precision is truncated. |
| `after` | query | string | No | Only return meetings that started after this time (RFC-3339). Sub-millisecond precision is truncated. |
| `cursor` | query | string | No | Opaque pagination cursor from a previous response's `nextCursor`. Do not construct cursors manually. |
| `limit` | query | integer | No | Number of meetings to return per page. Capped to **10** when `expand` includes `summary`, `actionItems`, or `chapters`, since expanded payloads are substantially larger.  |
| `expand` | query | string | No | Comma-separated list of fields to inline on each meeting. Allowed values are `summary`, `actionItems`, and `chapters` — same shape as on [`/meeting.info`](/docs/api/meeting-info). Use this to avoid N+ |

## Responses

### 200 - Meetings retrieved successfully

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `meetings` | object[] | No |  |
| `nextCursor` | string | No | Pagination cursor for the next page |

**meetings** (array item):

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `id` | string | Yes | Meeting ID |
| `title` | string | Yes | Meeting title |
| `subtitle` | string | No | Meeting subtitle |
| `start` | string | Yes | Meeting start time (RFC-3339) |
| `participantCount` | integer | Yes | Total number of participants |
| `hasVideo` | boolean | Yes | Whether the meeting was video recorded — a video track exists. `true` from the moment recording starts and it never flips back. It does **not** mean the recording is ready to fetch or play; read `vide |
| `videoStatus` | "none" | "processing" | "available" | Yes | Where this meeting's video recording is, which — unlike `hasVideo` — changes over time:  - `none` — no video track; the meeting was not recorded.   Always paired with `hasVideo: false`. - `processing` |
| `host` | MeetingParticipant | No | Meeting host as a participant object. Requires `user:read` scope; emails are only included with `user:read.email`. Omitted when the host cannot be resolved.  |
| `summary` | string | No | AI-generated meeting summary. Only present when `expand=summary`. |
| `actionItems` | ActionItem[] | No | AI-extracted action items. Only present when `expand=actionItems`. |
| `chapters` | object[] | No | Meeting chapters/segments. Only present when `expand=chapters`. |

**MeetingParticipant**:

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `type` | "member" | "guest" | Yes | Whether the participant is a workspace member or an external guest |
| `id` | string | Yes | The participant's address ID |
| `name` | string | Yes | Display name of the participant |
| `email` | string | No | Email address of the participant (requires `user:read.email` scope) |

**ActionItem** (array item):

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `id` | string | No | Action item ID. |
| `title` | string | Yes | Action item title. |
| `description` | string | No | Longer description of the action item. |
| `complete` | boolean | No | Whether the action item has been marked complete. Omitted when false. |
| `assigneeId` | string | No | User ID this item was explicitly assigned to, if any. |
| `suggestedAssigneeId` | string | No | AI-suggested assignee user ID, if any. |
| `suggestedAssigneeName` | string | No | Display name for the assignee — resolved from `assigneeId` when set, otherwise the AI-suggested name. |
| `assignedToMe` | boolean | No | Whether this item is assigned to the authenticated user. Personal access tokens only. |
| `suggestedForMe` | boolean | No | Whether this item is AI-suggested for the authenticated user. Personal access tokens only. |

**chapters** (array item):

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `name` | string | No |  |
| `start` | integer | No | Offset in milliseconds since the meeting's `start`. |
| `synopsis` | string | No |  |


#### Example Response

```json
{
  "meetings": [
    {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "title": "Weekly Team Standup",
      "start": "2025-04-07T10:00:00Z",
      "participantCount": 8,
      "hasVideo": true,
      "videoStatus": "available",
      "host": {
        "type": "member",
        "id": "ad1e9cc0-0ffd-47e5-895c-2630a73327b4",
        "name": "Alex Chen",
        "email": "alex.chen@example.com"
      }
    },
    {
      "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
      "title": "Product Review",
      "subtitle": "Q2 Roadmap",
      "start": "2025-04-06T14:00:00Z",
      "participantCount": 12,
      "hasVideo": true,
      "videoStatus": "processing",
      "host": {
        "type": "member",
        "id": "709b8a57-70bc-427a-b6f0-b16ba5297f8c",
        "name": "Jamie Park",
        "email": "jamie.park@example.com"
      }
    }
  ],
  "nextCursor": "YzE6MjAyNS0wNC0wNlQxNDowMDowMFo"
}
```

### 400 - Bad request.

### 401 - Presented invalid authentication credentials.

### 405 - An unsupported method was requested.

### 500 - An internal error occurred.

---

*Machine-readable API documentation.*
*Full documentation: https://developer.ro.am/docs/api/meeting-list*
