List appointments

.md

Everything between two moments, as appearances rather than rows.

Scopescalendar:read
GET/v1/me/calendar/events

What a grid draws. Repeating appointments are expanded, so a weekly meeting comes back once per week in the window rather than once with a rule to work out.

The window is bounded

At most 92 days per request. An app showing a year asks four times.

Request

ParameterDescription
fromISO 8601. Defaults to the start of today
untilISO 8601. Defaults to 31 days after from
calendars[]Only these calendars, by id from the calendar list. Defaults to every calendar in reach. Ids you cannot see are ignored rather than refused
curl -G https://api.proppertrading.com/v1/me/calendar/events \
  -H "Authorization: Bearer ptat_9f2c1a44_3b8e7d2f5c9a1b4e6d8f0a2c4e6b8d1f" \
  --data-urlencode "from=2026-08-24T00:00:00Z" \
  --data-urlencode "until=2026-08-31T00:00:00Z" \
  --data-urlencode "calendars[]=cal_r4d8h2m6t9w3k7nb"

Response

{
    "data": [
        {
            "id": "evt_k7m2p9x4q8r3t6v5",
            "object": "calendar_event",
            "occurrence_start": "2026-08-24T07:00:00+00:00",
            "calendar_id": "cal_r4d8h2m6t9w3k7nb",
            "title": "Weekly sync",
            "description": null,
            "location": null,
            "starts_at": "2026-08-24T07:00:00+00:00",
            "ends_at": "2026-08-24T07:30:00+00:00",
            "all_day": false,
            "timezone": "Europe/Amsterdam",
            "status": "confirmed",
            "source": "manual",
            "is_recurring": true,
            "recurrence_rule": "FREQ=WEEKLY;BYDAY=MO",
            "conference": {
                "provider": "google_meet",
                "url": "https://meet.google.com/abc-defg-hij",
                "meeting_id": null,
                "passcode": null
            },
            "organizer": {
                "name": "Sarah Klein",
                "email": "[email protected]"
            },
            "attendees": [
                {
                    "name": "Tom de Vries",
                    "email": "[email protected]",
                    "response": "accepted",
                    "is_organizer": false,
                    "is_optional": false
                }
            ],
            "reminders": [{ "minutes_before": 10, "channel": "in_app" }],
            "tags": [{ "id": "ctag_f7k3w9n2b5r8m4tx", "name": "Onboarding", "color": "emerald" }],
            "can_write": true
        }
    ],
    "meta": {
        "request_id": "req_01kz4bkr1aj1gv63d8fv3133ey",
        "from": "2026-08-24T00:00:00+00:00",
        "until": "2026-08-31T00:00:00+00:00"
    }
}
FieldDescription
idThe appointment, such as evt_k7m2p9x4q8r3t6v5. Every appearance of a series shares it. Use it in the URL to change, delete or answer it
calendar_idThe id of the calendar it is in, from the calendar list
occurrence_startWhich appearance this is, as the moment the rule originally put it. Null on an appointment that happens once. Send it back on every write
is_recurringWhether this is one of many
statusconfirmed, or pending for an invitation that arrived by mail and has not been answered
sourcemanual, mail for one that arrived as an invitation, or import
remindersOnly ever yours. A shared calendar does not hand you a colleague's alarms
tagsThe labels on it, whole rather than by id. Of the workspace, so the same label means the same thing in every calendar. Empty where the workspace has none
can_writeWhether this account may change it

At the busy level title reads "Busy" and every other field is empty or null. The words never leave the server.

Errors

StatusCodeMeaning
400invalid_dateA date was not ISO 8601
400invalid_windowuntil is not after from
400window_too_wideMore than 92 days apart
403insufficient_scopeThis device does not hold calendar:read
403calendar_not_permittedThe account may not open a calendar at all