Skip to main content

Calendar API

The Calendar API is available under /apis/v1/calendar and requires a Ration bearer token. Calendar, event, and scheduling data is tenant-scoped to the authenticated user.

Authorization: Bearer <ration_access_token>
Content-Type: application/json

Ration also supports CalDAV interoperability for compatible calendar clients. This REST reference covers only the public /apis/v1 API.

Calendars

List calendars

GET /apis/v1/calendar

Query parameterTypeRequiredDescription
limitIntegerNoPage size; defaults to 50.
cursorStringNoCursor returned by a prior page.

Response: a paginated calendar result returned by Ration, including calendar records and its cursor metadata.

Create a calendar

POST /apis/v1/calendar

Send calendar attributes at the top level.

{ "name": "Product", "color": "#006699" }

Response: { "calendar": { ... } }.

Update or delete a calendar

PUT /apis/v1/calendar/:calendar_id

Calendar attributes may be supplied either directly or nested under calendar:

{ "calendar": { "name": "Product delivery", "color": "#006699" } }

Response: { "calendar": { ... } }. The returned object is re-read after the update, so it is suitable for refreshing the client view.

DELETE /apis/v1/calendar/:calendar_id

Body/query fieldTypeRequiredDescription
move_to_calendar_idStringNoDestination calendar for existing events before deletion.

Successful deletion returns 204 No Content.

Events

List events or expanded instances

GET /apis/v1/calendar/:calendar_id/events

Query parameterTypeRequiredDescription
start, endISO 8601 date-timeNoEvent window. Omitted bounds default from the Unix epoch through five years ahead.
limitIntegerNoPage size; defaults to 50.
cursorStringNoEvent list cursor.

GET /apis/v1/calendar/:calendar_id/instances

This expands recurring events into occurrences. Both start and end are required ISO 8601 date-times; it also accepts limit and cursor.

Create or update an event

POST /apis/v1/calendar/:calendar_id/events

PUT /apis/v1/calendar/:calendar_id/events/:event_id

Place event attributes under event:

{
"event": {
"summary": "Design review",
"dtstart": "2026-08-10T09:00:00+01:00",
"dtend": "2026-08-10T10:00:00+01:00",
"description": "Review the proposed experience.",
"location": "Video meeting",
"attendees": [{ "email": "sam@example.com", "name": "Sam" }]
}
}

The event model supports standard calendar fields such as title/summary, date and time, description, location, attendees, recurrence, alarms, and scheduling metadata. Responses are { "event": { ... } }.

GET /apis/v1/calendar/:calendar_id/events/:event_id returns the same envelope. DELETE on that path returns 204 No Content.

Batch event changes

POST /apis/v1/calendar/:calendar_id/events/batch

{
"operations": {
"create": [{ "summary": "Kickoff", "dtstart": "…", "dtend": "…" }],
"update": [{ "event_id": "event-id", "summary": "Updated kickoff" }],
"delete": ["event-id"]
}
}

The create, update, and delete arrays may be placed directly at the top level instead. Response:

FieldTypeDescription
created, updated, deletedArrayOne result per requested operation.
*.statusStringok or error.
*.event, *.event_idObject or StringCreated/updated event or the affected event ID.
*.errorStringError detail for an individual failed operation.

RSVP and propose a time

PUT /apis/v1/calendar/:calendar_id/events/:event_id/rsvp

{ "response": "accepted" }

The response generates and dispatches a scheduling reply: { "status": "ok", "schedule_statuses": [...] }.

POST /apis/v1/calendar/:calendar_id/events/:event_id/proposals accepts the proposal fields required for an alternative meeting time and returns { "status": "proposal_sent", "schedule_statuses": [...] }.

Synchronization and scheduling

Incremental sync

POST /apis/v1/calendar/:calendar_id/sync

{ "sync_token": "token-from-a-prior-sync" }

Returns the changes since that token. An invalid token produces an error that includes valid_sync_token when Ration can supply a usable replacement.

iTIP scheduling messages

MethodPathRequired bodyResponse
POST/:calendar_id/scheduling/outboxics{ "status": "sent", "schedule_statuses": [...] }
POST/:calendar_id/scheduling/inboxics{ "status": "processed" }
GET/:calendar_id/scheduling/messagesPaginated scheduling-message result.
GET/:calendar_id/scheduling/messages/:message_id{ "message": { ... } }

Paths in this table are relative to /apis/v1/calendar. Supply a complete iCalendar (.ics) payload in ics. The outbox dispatches it to recipients; the inbox validates and applies it to the calendar.

Free/busy lookup

POST /apis/v1/calendar/scheduling/free_busy

{
"start_date": "2026-08-10T09:00:00+01:00",
"end_date": "2026-08-10T18:00:00+01:00",
"attendees": ["sam@example.com", { "email": "lee@example.com" }]
}

dtstart and dtend are accepted aliases for start_date and end_date. The response returns merged busy windows for the caller and each resolved attendee. Off-tenant addresses can be represented as unresolved because Ration cannot inspect their calendars.

Time polls and holiday availability

Time polls

MethodPathRequestResponse
POST/pollstitle, calendar_id, attendees, and at least two options (dtstart, dtend); optional draft.Created poll (201).
GET/polls/:idPoll, tally, and my_vote.
POST/polls/:id/voteoption_ids array.Updated poll and my_vote.
POST/polls/:id/finalize{ "poll": {...}, "event": {...} }.

Paths in this table are relative to /apis/v1/calendar. Only the organizer can finalize a poll. A poll needs at least two options and cannot be finalized without a winning vote.

Holidays and subscriptions

MethodPathDescription
GET/holidaysHoliday catalogue/lookup data.
GET/holidays/effective?year=2026Effective countries and holidays for the caller.
GET/holiday-subscriptionsTenant default, caller additions, effective countries, and can_manage.
PUT/holiday-subscriptionsSet the caller's countries array (or comma-separated string).
PUT/holiday-subscriptions/tenantTenant administrators set countries, custom_days, and speedy_meetings.

The tenant update requires the organization-management permission; otherwise it returns 403 { "error": "forbidden" }.

Errors

StatusMeaning
401Missing or invalid bearer authentication.
403Tenant context is required, or the caller lacks calendar/tenant permission.
404Calendar, event, poll, or scheduling message was not found.
400Invalid date range, invalid ICS payload, incomplete poll, or other invalid request.
422Calendar/event operation cannot be applied.