Cal.diy calendars and free/busy Use these capabilities to inspect connected calendars and availability, work with events, choose the destination for new bookings, or change conflict detection. This page owns all 21 operations in the calendar family. All operations use provider API version 2024-08-13. Every input and result in this family is restricted, contains PII, and requires redaction. Choose a calendar surface Cal.diy exposes two event surfaces. Choose one before constructing input: | Surface | Selector | Provider scope | | Unified connection | Integer connectionid; optional calendarId | A connection returned by Cal.diy | | Direct provider | calendar fixed to google | Google event and free/busy routes only | The broader provider checks accept google, office365, or apple. That does not expand the direct event surface: its published schema still requires "calendar": "google". Choose an operation Connection and availability reads | Capability | Provider request | Input | | cap:caldiy:calendar.list | GET /v2/calendars | Empty object | | cap:caldiy:calendar.provider.check | GET /v2/calendars/{calendar}/check | Provider | | cap:caldiy:calendar.icsfeed.check | GET /v2/calendars/ics-feed/check | Empty object | | cap:caldiy:calendar.busytime.list | GET /v2/calendars/busy-times | Range and calendars | | cap:caldiy:calendar.connection.list | GET /v2/calendars/connections | Empty object | | cap:caldiy:calendar.connection.freebusy.get | GET /v2/calendars/connections/{connectionid}/freebusy | Connection and range | | cap:caldiy:calendar.freebusy.get | GET /v2/calendars/{calendar}/freebusy | Google and range | All seven operations are low-risk, approval-free reads at the capability contract level. Unified connection events | Capability | Provider request | Risk | Approval | | cap:caldiy:calendar.connection.event.list | GET /v2/calendars/connections/{connectionid}/events | Low | No | | cap:caldiy:calendar.connection.event.get | GET /v2/calendars/connections/{connectionid}/events/{eventid} | Low | No | | cap:caldiy:calendar.connection.event.create | POST /v2/calendars/connections/{connectionid}/events | Medium | Required | | cap:caldiy:calendar.connection.event.update | PATCH /v2/calendars/connections/{connectionid}/events/{eventid} | Medium | Required | | cap:caldiy:calendar.connection.event.delete | DELETE /v2/calendars/connections/{connectionid}/events/{eventid} | High | Required | Direct Google events | Capability | Provider request | Risk | Approval | | cap:caldiy:calendar.event.list | GET /v2/calendars/{calendar}/events | Low | No | | cap:caldiy:calendar.event.get | GET /v2/calendars/{calendar}/events/{eventuid} | Low | No | | cap:caldiy:calendar.event.create | POST /v2/calendars/{calendar}/events | Medium | Required | | cap:caldiy:calendar.event.update | PATCH /v2/calendars/{calendar}/events/{eventuid} | Medium | Required | | cap:caldiy:calendar.event.delete | DELETE /v2/calendars/{calendar}/events/{eventuid} | High | Required | For every direct operation in this table, calendar must equal google. Routing and conflict detection | Capability | Provider request | Risk | Approval | | cap:caldiy:calendar.disconnect | POST /v2/calendars/{calendar}/disconnect | High | Required | | cap:caldiy:calendar.destination.update | PUT /v2/destination-calendars | Medium | Required | | cap:caldiy:calendar.selected.add | POST /v2/selected-calendars | Medium | Required | | cap:caldiy:calendar.selected.delete | DELETE /v2/selected-calendars | High | Required | Disconnect, both event deletes, and selected-calendar delete are destructive. Inspect calendar connections List connected calendars with an empty input: {} Use calendar.provider.check to test one provider connection: { "calendar": "google" } The exact provider enum is google, office365, or apple. Provider check shows whether the authenticated integration is connected and healthy at that request boundary. It does not prove that every calendar is visible or writable. calendar.icsfeed.check also accepts an empty object and checks the authenticated user's ICS feed connection. calendar.connection.list returns credential-safe unified connection identifiers; the connector does not publish their provider-owned response fields. These reads inspect connections that already exist. Provider connect and save routes that establish browser OAuth sessions or credentials remain outside the agent-callable business-operation surface. Read busy time across selected calendars calendar.busytime.list requires a time zone, a bounded range, and at least one explicit calendar: { "timeZone": "UTC", "dateFrom": "2026-08-03", "dateTo": "2026-08-04T18:00:00Z", "calendarsToLoad": [ { "credentialId": 42, "externalId": "primary@example.com" } ] } | Field | Constraint | | timeZone | Non-empty string | | dateFrom, dateTo | ISO date or date-time string | | calendarsToLoad | Array with at least one object | | credentialId | Integer required in each object | | externalId | Non-empty string required in each object | The client sends these values as query parameters. Nested calendar objects use bracket notation such as calendarsToLoad[0][credentialId]. The schema does not set a maximum or require unique calendar objects, and it does not assert that dateFrom precedes dateTo. Busy intervals are scheduling evidence, not a reservation or a guarantee that a later booking will succeed. Read unified connection events List events for a unified connection with a required range: { "connectionid": 73, "from": "2026-08-03T00:00:00Z", "to": "2026-08-04T00:00:00Z", "timeZone": "UTC", "calendarId": "team@example.com" } connectionid, from, and to are required. from and to accept either an ISO date or date-time. Optional timeZone and calendarId must be non-empty. The connection id is a path segment; all range fields and calendarId become query parameters. Read one event with connectionid and a non-empty eventid. An optional calendarId selects a calendar within that connection and is sent as a query parameter: { "connectionid": 73, "eventid": "provider-event-uid", "calendarId": "team@example.com" } Create a unified connection event Create requires the connection, title, start, and end: { "connectionid": 73, "calendarId": "team@example.com", "title": "Architecture review", "start": { "time": "2026-08-03T10:00:00Z", "timeZone": "UTC" }, "end": { "time": "2026-08-03T10:30:00Z", "timeZone": "UTC" }, "description": "Review the proposed integration boundary.", "attendees": [ { "email": "avery@example.com", "name": "Avery Patel" } ] } title must be non-empty. Both start and end require a date-time time and a non-empty timeZone. description may be a string or null. attendees may contain objects with a required email and optional name; the array has no published minimum or uniqueness constraint. Additional fields are rejected at the event, date-time, and attendee object boundaries. calendarId is optional. The client puts it in the query while sending event details as JSON. The connector contract carries write and externalnetwork, but not sendmessage. Attendee input is therefore not evidence that the provider sent an invitation. The create operation names calendar.connection.event.delete as best-effort compensation. Compensation requires a separate approval and is not automatic. Update or delete a unified connection event Update requires connectionid and eventid. It may include calendarId and any of these body fields: | Field | Constraint | | title | String; an empty string passes the connector schema | | start, end | Object with optional date-time time and string timeZone | | description | String or null | | attendees | Array or null | | status | accepted, pending, declined, cancelled, or null | An attendee update requires email and may include name, self, optional, host, and responseStatus. Response status accepts accepted, pending, declined, needsAction, or null. The schema allows an identifier-only update and empty start or end objects. Such input can pass local validation without expressing a useful provider change. Include only an intentional, provider-supported patch. Delete uses connectionid and eventid, plus optional calendarId. The two ids become path segments and calendarId becomes a query parameter. Delete is high risk and has no rollback contract. Both update and delete first read the exact unified event. A successful preflight proves only that the event was readable before mutation. Read, create, or change a direct Google event The direct surface mirrors the unified event model with these selector changes: • every input requires "calendar": "google"; • list also requires from and to, with optional timeZone and calendarId; • get and delete require a non-empty eventuid; • create has no calendarId field; • update requires eventuid and uses the shared optional patch fields. Create and update use the field constraints described for unified events. Direct create names calendar.event.delete as best-effort compensation. Direct update and delete first run calendar.event.get for the same calendar and eventuid. The direct schema does not publish Office 365 or Apple event variants. Use a unified connection when its returned identifier is the intended routing model. Read free/busy Unified free/busy requires connectionid, from, and to. Direct free/busy requires calendar fixed to google, from, and to. Both accept optional non-empty timeZone; all range fields are query parameters. { "connectionid": 73, "from": "2026-08-03", "to": "2026-08-04", "timeZone": "UTC" } The input schema accepts dates or date-times and does not enforce ordering or a maximum interval. A free/busy response is provider-owned and restricted. It does not by itself apply schedule rules, event-type buffers, reservations, or booking policy. Change the destination calendar calendar.destination.update changes where new bookings are written: { "integration": "googlecalendar", "externalId": "primary@example.com" } integration must be applecalendar, googlecalendar, or office365calendar. externalId is required and non-empty. An optional non-empty delegationCredentialId selects delegated provider credentials. The connector first lists calendars. This does not prove that the requested externalId appeared in that result; provider validation still decides the mutation. The operation is medium risk and has no compensating capability. Add or remove a conflict calendar Add requires an integration name, external calendar id, and integer credential id: { "integration": "googlecalendar", "externalId": "team@example.com", "credentialId": 42 } All three fields are required. integration and externalId must be non-empty; credentialId is an integer. Optional delegationCredentialId must be non-empty. The schema does not constrain integration to the destination calendar enum. Remove uses the same route but requires credentialId as a non-empty string, not an integer. The client sends integration, externalId, credentialId, and optional delegationCredentialId as query parameters on DELETE. Both operations first list calendars. Add declares calendar.selected.delete as best-effort compensation. Remove is destructive and has no further rollback. Disconnect a provider credential Disconnect requires a provider and integer credential id: { "calendar": "office365", "id": 42 } calendar must be google, office365, or apple. The client sends a POST to the provider-specific disconnect path and leaves id in the JSON body. Before dispatch, it checks that provider connection without using the id. Integer identifiers in this family have no additional minimum in the published schema. Cal.diy can still reject a value outside the provider's domain. The operation is high risk and destructive. It deletes an owned credential and invalidates the connection. No compensation or automatic credential recovery is declared. Preflight reads | Mutation | Connector preflight | | Unified or direct event create | calendar.list | | Destination update | calendar.list | | Selected-calendar add or delete | calendar.list | | Unified event update or delete | Exact unified event get | | Direct event update or delete | Exact direct event get | | Calendar disconnect | Provider check for calendar | A preflight is a point-in-time read, not a lock, plan, reservation, or approval. Shared read contract All 11 reads are low risk, synchronous, retry-safe, and eligible for connector retry. Their idempotency key is optional, action-scoped, and collision-checked against the input hash. No capability-level approval is required. Identity, tenant, external-account, credential-scope, and restricted-data policy still apply to every read. Shared mutation contract All ten mutations require: | Contract field | Value | | Human approval | Required | | Approval selector | Tenant policy | | Approval validity window | 900,000 ms | | Approval evidence | Reason, input snapshot, policy decision | | Idempotency | Required; external-account scope | | Collision behavior | Revalidate input hash | | Connector retry | Not supported | | Retry safety | Unsafe | | Execution | Synchronous only | | Transaction modes | dryrun, plan, commit, reconcile | | Plan before commit | Not required | | Dry-run fidelity | Policy and schema only | Six non-destructive mutations are medium risk. Calendar disconnect, both event deletes, and selected-calendar delete are high risk and destructive. None of the ten mutations carries the sendmessage side-effect marker. Event create on either surface and selected-calendar add each declare one best-effort delete compensation. All other mutations declare rollback as not supported. Never interpret a compensation declaration as automatic execution or restoration of invitations, notifications, external state, or history. Result and redaction contract The connector returns the validated provider JSON body as AIP output. A non-empty string status is required. data, pagination, and additional provider fields are optional; their shapes are not guaranteed by the connector schema. The connector recursively replaces secret-, key-, and token-named values with [REDACTED]. This targeted redaction does not remove event titles, attendee addresses, calendar ids, busy intervals, descriptions, or other PII unless a field name matches the secret redactor. Keep the complete output restricted. Failures and recovery | Failure | Relevant cause | Safe response | | connector.caldiy.invalidaction | Missing selector, invalid range shape, invalid enum, or unknown field | Correct the exact input before another call | | connector.caldiy.policy | Mutation omitted its required idempotency key | Preserve approved input and add the missing key | | connector.caldiy.idempotencycollision | One key owns different mutation input | Stop and inspect the original action | | connector.caldiy.inflight | A matching calendar mutation is executing | Read durable state and wait | | connector.caldiy.outcomeunknown | Prior provider dispatch cannot be proved | Reconcile; do not create a replacement key | | connector.caldiy.authentication | Provider returned 401 or 403 | Verify account binding, credential revision, and calendar ownership | | connector.caldiy.stateconflict | Provider returned 409 or 412 | Refresh event or calendar state and review the mutation | | connector.caldiy.ratelimited | Provider returned 429 | Retry reads within policy; reconcile mutations | | connector.caldiy.remotetemporary | Provider returned a server error | Retry reads within policy; reconcile mutations | | connector.caldiy.transport | Provider exchange failed | Retry reads only; treat dispatched mutations as uncertain | | connector.caldiy.invalidprovideroutput | Successful response lacked valid status | Preserve evidence and reconcile a mutation | Permanent rejection, invalid credentials, oversized responses, and durable settlement failures use the common Cal.diy error family. Gateway and lifecycle errors are described in the global error reference (../../../reference/errors.md). Verify calendar handling For a read, retain the capability, exact selector and range, actor, tenant, external account, provider status, and provider request id when present. Verify that the result remains inside its approved restricted-data destination. For a mutation, also retain approval evidence and the original idempotency key. Wait for a completed durable result, then read the exact event or list calendar state. For an uncertain dispatch, reconcile the original operation before any new action. These checks validate application handling. They do not prove invitation delivery, provider-wide visibility, live availability, cross-provider qualification, or production readiness. Related documentation • Cal.diy capability index (README.md) • Core booking capabilities (bookings.md) • Authentication and tenant routing (../getting-started/authentication-and-tenant-routing.md) • Transactions and compensation (../../../concepts/transactions-and-compensation.md) • Error reference (../../../reference/errors.md)