Invitations
Pro plan. Requires a hosted calendar. View plans.
CalendarPipe hosted calendars support the full iTIP invitation workflow. Create an event with attendees and CalendarPipe handles REQUEST and CANCEL delivery automatically. Attendees receive standard calendar invitations and their RSVP responses route back to your hosted calendar.
How Invitations Work
The invitation lifecycle follows these steps:
- Create an event with attendees on a hosted calendar via the API.
- CalendarPipe sends an iTIP REQUEST email to each attendee.
- Attendees receive a standard calendar invitation in their email client or calendar app.
- When attendees RSVP, responses route back to the calendar's
calendarEmailaddress. - Poll or receive webhooks to get RSVP status updates in your application.
Creating Events with Attendees
To trigger an invitation flow, include an attendees array when creating an event on a hosted calendar:
POST /api/v1/calendars/hosted:{id}/events
Authorization: Bearer `<api_key>`
Content-Type: application/json
{
"title": "Strategy Session",
"start_at": "2026-03-25T10:00:00Z",
"end_at": "2026-03-25T11:00:00Z",
"timezone": "America/New_York",
"attendees": [
{ "email": "alice@example.com", "displayName": "Alice" },
{ "email": "bob@example.com", "displayName": "Bob" }
]
}
Response (201):
{
"data": {
"uid": "abc123-event-uid",
"title": "Strategy Session",
"start_at": "2026-03-25T10:00:00Z",
"end_at": "2026-03-25T11:00:00Z",
"attendees": [
{ "email": "alice@example.com", "displayName": "Alice" },
{ "email": "bob@example.com", "displayName": "Bob" }
]
}
}
CalendarPipe sends an iTIP REQUEST email to each attendee automatically after the event is created. You do not need to trigger delivery separately.
Retrying safely
A create that times out may still have succeeded, and retrying it blindly makes a second event — with a second invitation to everyone on it. Send an Idempotency-Key header to make the retry safe:
POST /api/v1/calendars/hosted:{id}/events
Idempotency-Key: meeting-4821
A repeat of the same key on the same calendar returns the event the first request created, with status 200 instead of 201, and sends no further invitations. Keys are scoped per calendar and may be up to 255 characters. Pick something derived from your own record of the meeting rather than a random value, so the retry can reproduce it.
Limits
- Attendee cap: each hosted event may include at most 500 attendees. This applies to events created through the API and to events written by a CalDAV client; requests that exceed it return
400. - Events already above the cap: an event that already has more than 500 attendees stays fully usable. You can still edit it, remove attendees, and cancel it — an update is only rejected if it would add attendees beyond the count the event already has.
- Email rate limits: outbound mail is limited per user per hour. Each row below is its own budget — they are counted separately and do not draw from a shared total. Exceeding any of them returns
429.
| Limit | |
|---|---|
| Invitations and cancellations you send | 500 / hour |
| RSVP replies you send to an organizer | 500 / hour |
| Invitations sent by your sync rules | 500 / hour |
Calendar Email Address
Each hosted calendar has a stable inbound email address returned as calendarEmail (format cal-{emailToken}@in.calendarpipe.com).
This address serves two purposes:
- Outbound: It is the organizer address shown on invitations sent to attendees
- Inbound: RSVP replies from attendees are routed back to this address and recorded on the hosted calendar
calendarEmail is independent of feedToken. Regenerating the feed token rotates the ICS feed URL only — invitation threads keep routing to the same address.
The address routes mail to the calendar; it does not by itself authorize changes to it. Inbound calendar mail is only applied when the sending mailbox matches the identity it is acting as:
| Inbound message | Must be sent from |
|---|---|
| RSVP reply | The attendee whose response it carries |
| Cancellation | The organizer recorded on the invitation |
| Update to an existing invite | The organizer recorded on the invitation |
| New invitation | The organizer named in the invitation itself |
Mail that does not match is accepted and ignored. In practice this is automatic -- calendar clients send from the mailbox they act as -- but an integration that relays invitations or RSVPs from a shared or delegated mailbox will need to send as the attendee or organizer.
Cancelling Events
To cancel an event and notify all attendees:
DELETE /api/v1/calendars/hosted:{id}/events/{uid}
Authorization: Bearer `<api_key>`
Response (204): No content. CalendarPipe sends an iTIP CANCEL email to all attendees automatically.
Receiving RSVPs
Once attendees respond to an invitation, there are two ways to receive their RSVP status:
Polling
Query the invitations list for a specific status:
GET /api/v1/hosted-calendars/{id}/invitations?status=pending
Authorization: Bearer `<api_key>`
The status query parameter accepts:
| Value | Description |
|---|---|
pending | Awaiting response from attendee |
ACCEPTED | Attendee accepted the invitation |
DECLINED | Attendee declined the invitation |
TENTATIVE | Attendee tentatively accepted |
Webhooks
For real-time RSVP delivery without polling, register a webhook on the hosted calendar. See the Webhooks guide for registration steps, payload format, and HMAC signature verification.
Responding to Invitations
In agent-to-agent scenarios where your hosted calendar receives an invitation from another organizer, your agent can respond programmatically.
Listing invitations needs the invitations:read scope and responding needs invitations:write — nothing else. An agent whose only job is to accept meetings should hold exactly those two, so a leaked key cannot reach the rest of the account. Accepting adds the event to the calendar without needing events:write, because the event comes from the invitation the organizer sent.
POST /api/v1/hosted-calendars/{id}/invitations/{uid}/respond
Authorization: Bearer `<api_key>`
Content-Type: application/json
{ "status": "ACCEPTED" }
Valid values for status:
| Value | Description |
|---|---|
ACCEPTED | Accept the invitation |
DECLINED | Decline the invitation |
TENTATIVE | Tentatively accept the invitation |
Repeated calls with the same status are idempotent — CalendarPipe returns success without sending another reply email to the organizer. Changing status (for example ACCEPTED → DECLINED) sends a new reply. New replies draw on the RSVP reply budget in Limits; exceeding it returns 429.
Loop Prevention
The organizer email on any event must NOT be a cal-*@in.calendarpipe.com address. CalendarPipe skips internal routing for events where the organizer is a cal-* address to prevent infinite invitation delivery loops. Always use a real external email address or the organizerDisplayName field when creating hosted calendars intended to send invitations.
If you are creating a hosted calendar specifically for invitation sending, set a meaningful organizerDisplayName but ensure the underlying email identity is not a CalendarPipe inbound address.
Related
- Webhooks — receive real-time RSVP notifications instead of polling.
- Hosted Calendars — create and manage the calendars that power invitations.
- Agent Skills — pre-built skills that handle invitation flows from AI agents.