# AddCal API Documentation

The official AddCal API documentation. This comprehensive guide provides developers with everything needed to integrate calendar and event management functionality into their applications. Our RESTful API enables seamless creation, management, and sharing of events across multiple platforms and calendar services.

- Base URL: `https://addcal.co`
- Authentication: HTTP Bearer token. You can retrieve your token from the [API Tokens page](https://addcal.co/user/api-tokens) in your dashboard.
- OpenAPI document: https://addcal.co/docs.openapi
- Interactive reference: https://addcal.co/docs

Send the token on every request:

```
Authorization: Bearer YOUR_API_TOKEN
Accept: application/json
```

## Sections

- [Create Event](https://addcal.co/docs/create-event.md)
- [Calendars](https://addcal.co/docs/calendars.md)
- [Calendars > Subscribers](https://addcal.co/docs/subscribers.md)
- [Events](https://addcal.co/docs/events.md)
- [Events > RSVPs](https://addcal.co/docs/rsvps.md)
- [Events > Invites](https://addcal.co/docs/invites.md)
- [Account](https://addcal.co/docs/account.md)
- [Dynamic Links](https://addcal.co/docs/dynamic-links.md)
- [Endpoints](https://addcal.co/docs/endpoints.md)

## Calendars > Subscribers

APIs for reading the people who have subscribed to a calendar.

## Matching subscribers to your own records

Pass `external_id` when someone subscribes and that value comes back here, so an AddCal
subscriber can be reconciled against a record in your own system.

Set it on an embed as `data-external-id`, or on a link to a hosted calendar page as
`?external_id=`:

```
<div class="addcal-btn" data-calendar="cal_abc123" data-external-id="member-8412"></div>

https://addcal.co/c/cal_abc123?external_id=member-8412
```

**The subscribe route drops a malformed id silently.** It accepts 1-191 characters matching
`^[A-Za-z0-9._:-]+$`; anything else is discarded and the subscribe still succeeds, with no
error and no field in the response. That is deliberate: the person subscribing is a real
visitor, and an id that only matters to your integration should not fail their subscribe.

The practical consequence is that an email address, a base64 token, or anything over 191
characters will never reach this endpoint, and the first sign of it is a subscriber that
cannot be matched. Validate the shape on your side before you send it. This endpoint does
reject a malformed `external_id` with a 422, so it can be used to check an id's shape.

To find whether one of your records is subscribed, filter by it and check whether the
response contains any rows:

```
GET /api/calendars/cal_abc123/subscribers?external_id=member-8412
```

### List subscribers

`GET /api/calendars/{calendar_public_id}/subscribers`

**Path parameters**

- `calendar_public_id` (string, required): The ID of the calendar public.

**Query parameters**

- `external_id` (string, optional): Only return subscribers carrying this external id.
- `per_page` (integer, optional): Number of results per page (1-100)

**Body parameters** (`application/json`)

- `external_id` (string, optional): Must match the regex /^[A-Za-z0-9._:-]+$/. Must not be greater than 191 characters.
- `per_page` (integer, optional): Must be at least 1. Must not be greater than 100.

**Example request**

```bash
curl --request GET \
  --url 'https://addcal.co/api/calendars/{calendar_public_id}/subscribers' \
  --header 'Authorization: Bearer YOUR_API_TOKEN' \
  --header 'Accept: application/json'
```

**Response 200**

```json
{
    "data": [
        {
            "uid": "vuh5fsk8wh62wr",
            "public_id": "sub_vuh5fsk8wh62wr",
            "service": "outlook",
            "name": null,
            "email": null,
            "data": null,
            "status": "inactive",
            "created_at": "2026-08-28T03:20:12.000000Z",
            "updated_at": "2026-08-28T03:20:12.000000Z"
        },
        {
            "uid": "d2w829050qqm73",
            "public_id": "sub_d2w829050qqm73",
            "service": "ics",
            "name": null,
            "email": null,
            "data": null,
            "status": "inactive",
            "created_at": "2026-08-28T03:20:12.000000Z",
            "updated_at": "2026-08-28T03:20:12.000000Z"
        }
    ]
}
```
