**Table of contents:**
<%= toc %>

All requests use your team's API token and return JSON.

> Note: You can directly access a markdown version of these docs [here](/help/api.md) - perfect for feeding to agents / LLMs.

## Authentication

Pass your API token as a Bearer token in the `Authorization` header:

```
Authorization: Bearer al_live_...
```

You can generate an API token from your team's settings page.

## Rate Limits

Each response includes rate-limit headers:

| Header                  | Description                          |
| ----------------------- | ------------------------------------ |
| `X-RateLimit-Limit`     | Your monthly request quota           |
| `X-RateLimit-Remaining` | Requests remaining this month        |
| `X-RateLimit-Reset`     | Unix timestamp when the quota resets |

Currently, our Teams plan can make up to 10,000 requests/month before becoming rate-limited.

## Errors

Errors return a JSON body with a `type` and `message`:

```json
{
  "error": {
    "type": "authentication_error",
    "message": "Invalid or missing API token."
  }
}
```

| Type                    | Meaning                               |
| ----------------------- | ------------------------------------- |
| `authentication_error`  | Missing or invalid API token          |
| `invalid_request_error` | Bad parameters or resource not found  |
| `plan_error`            | API access not available on your plan |
| `quota_exceeded_error`  | Monthly request quota exceeded        |
| `rate_limit_error`      | Too many requests per minute          |

## Pagination

List endpoints use cursor-based pagination.

Pass `limit` (1 - 50, default 25) and `starting_after` (the `id` of the last item) to page through results:

```sh
GET /api/v1/meetings?limit=10&starting_after=mtg_abc123
```

### Response

```json
{
  "object": "list",
  "data": [{}, {}, {}],
  "has_more": true,
  "next_cursor": "mtg_xyz789"
}
```

When `has_more` is `true`, pass `next_cursor` as the `starting_after` param to fetch the next page. When `has_more` is `false`, `next_cursor` is `null`.

## Endpoints

### Meetings

#### LIST Meetings

```
GET /api/v1/meetings
```

Returns meetings for your organization, newest first.

**Parameters:**

| Param            | Description                                  |
| ---------------- | -------------------------------------------- |
| `status`         | Filter by `live` or `ended`                  |
| `started_after`  | Only meetings started after this (ISO 8601)  |
| `started_before` | Only meetings started before this (ISO 8601) |
| `limit`          | Results per page (1–50, default 25)          |
| `starting_after` | Cursor for pagination (a meeting `id`)       |

**Example request:**

```bash
curl https://attendlist.com/api/v1/meetings \
  -H "Authorization: Bearer al_live_..." \
  -d status=ended \
  -d limit=10 \
  -G
```

**Response:**

```json
{
  "object": "list",
  "has_more": false,
  "next_cursor": null,
  "data": [
    {
      "id": "mtg_abc123",
      "object": "meeting",
      "code": "abc-defg-hij",
      "title": "Weekly standup",
      "status": "ended",
      "started_at": "2026-07-01T09:00:00Z",
      "ended_at": "2026-07-01T09:30:00Z",
      "duration_seconds": 1800,
      "tags": ["engineering"],
      "created_at": "2026-07-01T09:00:00Z"
    }
  ]
}
```

#### GET Meeting

```
GET /api/v1/meetings/:id
```

Returns a single meeting with its participants and sessions.

**Example request:**

```bash
curl https://attendlist.com/api/v1/meetings/mtg_abc123 \
  -H "Authorization: Bearer al_live_..."
```

**Response:**

```json
{
  "id": "mtg_abc123",
  "object": "meeting",
  "code": "abc-defg-hij",
  "title": "Weekly standup",
  "status": "ended",
  "started_at": "2026-07-01T09:00:00Z",
  "ended_at": "2026-07-01T09:30:00Z",
  "duration_seconds": 1800,
  "tags": ["engineering"],
  "created_at": "2026-07-01T09:00:00Z",
  "participants": [
    {
      "id": "pt_xyz789",
      "object": "participant",
      "display_name": "Jane Smith",
      "email": "jane@example.com",
      "photo_url": "https://...",
      "created_at": "2026-07-01T09:00:00Z"
    }
  ],
  "participant_sessions": [
    {
      "id": "ps_def456",
      "object": "participant_session",
      "participant_id": "pt_xyz789",
      "meeting_id": "mtg_abc123",
      "joined_at": "2026-07-01T09:00:00Z",
      "left_at": "2026-07-01T09:30:00Z",
      "screenshare_session": false,
      "duration_seconds": 1800,
      "created_at": "2026-07-01T09:00:00Z"
    }
  ]
}
```

## Resources

### Meeting

A meeting which was tracked by AttendList to produce an attendance report.

| Field              | Type        | Description                                        |
| ------------------ | ----------- | -------------------------------------------------- |
| `id`               | string      | Unique identifier for the meeting                  |
| `object`           | string      | Always `"meeting"`                                 |
| `code`             | string      | The Google Meet meeting code (e.g. `abc-defg-hij`) |
| `title`            | string      | Meeting title                                      |
| `status`           | string      | Either `"live"` or `"ended"`                       |
| `tags`             | string[]    | List of tag names applied to this meeting          |
| `duration_seconds` | integer     | Meeting duration in seconds                        |
| `started_at`       | string      | When the meeting started (ISO 8601)                |
| `ended_at`         | string/null | When the meeting ended (ISO 8601)                  |
| `created_at`       | string      | When the record was created (ISO 8601)             |

The **Get** endpoint also includes `participants` and `participant_sessions`:

### Participant

Participants (attendees) of a given Meeting.

| Field          | Type        | Description                            |
| -------------- | ----------- | -------------------------------------- |
| `id`           | string      | Unique identifier for the participant  |
| `object`       | string      | Always `"participant"`                 |
| `display_name` | string      | The participant's display name         |
| `email`        | string/null | The participant's email address        |
| `photo_url`    | string      | URL to the participant's profile photo |
| `created_at`   | string      | When the record was created (ISO 8601) |

### ParticipantSession

An instance of a Participant joining a Meeting. A Participant can have multiple ParticipantSessions if they left and rejoined a Meeting multiple times.

| Field                 | Type        | Description                                                                                         |
| --------------------- | ----------- | --------------------------------------------------------------------------------------------------- |
| `id`                  | string      | Unique identifier for the session                                                                   |
| `object`              | string      | Always `"participant_session"`                                                                      |
| `screenshare_session` | boolean     | Whether this session is a screenshare or regular session (only accurate once the session has ended) |
| `duration_seconds`    | integer     | Session duration in seconds                                                                         |
| `joined_at`           | string      | When the participant joined (ISO 8601)                                                              |
| `left_at`             | string/null | When the participant left (ISO 8601)                                                                |
| `created_at`          | string      | When the record was created (ISO 8601)                                                              |
| `meeting_id`          | string      | The `id` of the meeting                                                                             |
| `participant_id`      | string      | The `id` of the participant                                                                         |

## Best Practices

- **Cache responses locally.**
  - Your API quota is limited, so avoid fetching the same data repeatedly. Store response data on your side after the first request, and only re-fetch when you need fresh results (e.g. for new meetings).
- **Use `starting_after` to sync incrementally.**
  - Track the `id` of the most recent meeting you've fetched and cached locally. On subsequent requests, pass it as `starting_after` to only retrieve meetings you haven't seen yet, rather than re-fetching your entire history each time (which can quickly burn your API quota).
