Email, calendar & files

Calendar

List calendars and events, create events with Google Meet or Teams links, answer invitations and find free meeting slots across Google and Microsoft mailboxes.

Work in your users' own Google Calendar or Outlook Calendar. Create a booking with a video link, answer an invitation, or find a time that suits several people across Google and Microsoft accounts at once. Every call takes the accountId of an account connected with the calendar area.

#List calendars and events

GET /v1/calendar/calendars?accountId=... returns the user's calendars with primary, timezone and readOnly. Use an id from it as calendarId, or primary for the main calendar.

GET /v1/calendar/events returns events between from and to (both required):

curl "https://api.pozy.ai/v1/calendar/events?accountId=6710c501e4b0d2f1a8c95e77&from=2026-11-02T00:00:00Z&to=2026-11-09T00:00:00Z" \
  -H "Authorization: Bearer $POZY_API_KEY"
Parameter What it does
calendarId Which calendar; primary when left out
expandRecurring With true, the default, a repeating event comes back once per occurrence. With false you get the series itself
showCancelled true adds cancelled events; they are hidden by default
title, location, icalUid Filter on these
timezone Times in the response are given in this IANA zone
sortOrder, cursor, limit Ascending unless you say otherwise; 50 events a page by default, 200 at most

Each event has title, start, end, allDay, participants (with their response status), conferencing (provider and url), status and a link to open it in the provider's app.

#Create an event

Participants get invitations from the user's own calendar. Set conferencing to google_meet on Google or teams on Microsoft to attach a video link.

curl -X POST https://api.pozy.ai/v1/calendar/events \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "accountId": "6710c501e4b0d2f1a8c95e77",
    "title": "Content review with Jordan",
    "start": "2026-11-05T10:00:00+01:00",
    "end": "2026-11-05T10:30:00+01:00",
    "timezone": "Europe/Madrid",
    "participants": [{ "email": "jordan@client.example", "name": "Jordan Lee" }],
    "conferencing": "google_meet",
    "reminders": { "useDefault": false, "overrides": [{ "minutes": 15 }] },
    "metadata": { "bookingId": "bk_9081" }
  }'
Field Rules
calendarId The calendar that gets the event; primary if omitted
title Required; 1,000 characters at most
start, end Date-times in ISO 8601 with an offset. For an all-day event, plain YYYY-MM-DD dates plus allDay: true
timezone The event's IANA time zone
participants A list of { email, name? }, 100 at most
recurrence On Google, as many as 5 lines of RRULE, EXRULE, RDATE or EXDATE. On Outlook, a single RRULE whose frequency is DAILY, WEEKLY, MONTHLY or YEARLY
reminders { useDefault, overrides }. Google accepts 5 overrides, each between 0 and 40,320 minutes; Outlook uses only the first one
conferencing google_meet on Google, teams on Microsoft. Asking a provider for the other one's meetings gets 400
description, location, busy, visibility visibility takes default, public or private
metadata Your own string keys and values, stored with the event

PATCH /v1/calendar/events/{eventId} changes an event and takes the same fields. DELETE /v1/calendar/events/{eventId}?accountId=... removes it. Participants get the usual invitation, update or cancellation email for each, exactly as if the user had made the change in the calendar app.

Events on other calendars

Reading, changing, deleting and answering an event all look in the primary calendar by default. For an event elsewhere, add calendarId: as a query parameter on GET and DELETE, and in the body on PATCH and RSVP. If you get 404 resource_not_found, the event is most likely on a different calendar.

#Answer an invitation

cURL
curl -X POST https://api.pozy.ai/v1/calendar/events/6p1kq2rbc5i3eb9g/rsvp \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "accountId": "6710c501e4b0d2f1a8c95e77", "status": "accepted", "comment": "See you there" }'

status is accepted, declined or tentative. comment (up to 1,000 characters) goes to the organizer. The mailbox must be an invited attendee.

#Find a meeting time

POST /v1/calendar/free-busy returns busy blocks for up to 10 mailboxes, Google and Microsoft mixed. POST /v1/calendar/availability turns them into bookable slots:

curl -X POST https://api.pozy.ai/v1/calendar/availability \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "participants": [{ "accountId": "6710c501e4b0d2f1a8c95e77" }, { "accountId": "6710c50ce4b0d2f1a8c95e82" }],
    "from": "2026-11-02T00:00:00Z",
    "to": "2026-11-07T00:00:00Z",
    "durationMinutes": 30,
    "buffer": { "before": 10, "after": 10 },
    "defaultOpenHours": [{ "days": [1, 2, 3, 4, 5], "timezone": "Europe/Madrid", "start": "09:00", "end": "17:00" }]
  }'
Field Rules
participants Between 1 and 10 entries of { accountId, openHours? }
durationMinutes How long each slot is, from 5 to 480
intervalMinutes Minutes from one slot's start to the next, from 5 to 240; 30 by default
roundTo Moves from forward to the next multiple of this many minutes (5 to 60)
buffer Free minutes to keep { before, after } other meetings, 240 at most on each side
defaultOpenHours, openHours When people work: days (Sunday is 0), timezone, start and end in HH:MM, and exdates to skip
method collective, the default, needs every participant free. max_availability needs one, and accountIds says which

Both the free-busy and availability calls use the primary calendar of each mailbox. Outlook's data comes in 15-minute blocks.

#Webhook events

Any change to the primary calendar fires calendar.event.created, calendar.event.updated or calendar.event.deleted, no matter whether it came through Pozy or from the user's own calendar app. The payload has account, plus calendarEvent with the event's id and changeType; read the event to see how it looks now. A provider may report one change more than once, so deduplicate on the event id.

Event When it fires
calendar.event.created Calendar event created.
calendar.event.updated Calendar event updated.
calendar.event.deleted Calendar event deleted.

#Errors

Error Cause Fix
400 invalid_field_value, param: conferencing teams on Google or google_meet on Microsoft Use the provider's own option
400 "not an attendee" RSVP from a mailbox that was not invited RSVP from the invited mailbox
404 resource_not_found Wrong calendar, or the event was deleted Pass the event's calendarId
412 account_scope_missing No calendar area on the account Reconnect with calendar in scopes

#Endpoints

Endpoint What it does
GET /v1/calendar/calendars List calendars
GET /v1/calendar/events List events in a window
POST /v1/calendar/events Create an event
GET /v1/calendar/events/{eventId} Get an event
PATCH /v1/calendar/events/{eventId} Update an event
DELETE /v1/calendar/events/{eventId} Delete an event
POST /v1/calendar/events/{eventId}/rsvp Respond to an invitation
POST /v1/calendar/free-busy Busy blocks for one or more accounts
POST /v1/calendar/availability Find meeting slots across accounts