Cal.diy booking capabilities Use these capabilities to find, create, reschedule, cancel, confirm, decline, mark, reassign, or relocate a Cal.diy booking. This page owns 12 core lifecycle operations. A separate capability page owns the 10 attendee, guest, calendar link, reference, recording, transcript, and conferencing-session operations. All booking operations use provider API version 2024-08-13. Booking data is restricted, contains PII, and requires redaction throughout this family. Choose an operation Find a booking | Capability | Provider request | Risk | Approval | | cap:caldiy:booking.list | GET /v2/bookings | Low | No | | cap:caldiy:booking.get | GET /v2/bookings/{bookinguid} | Low | No | | cap:caldiy:booking.getbyseat | GET /v2/bookings/by-seat/{seatuid} | Low | No | Create or move a booking | Capability | Provider request | Risk | Plan required | | cap:caldiy:booking.create | POST /v2/bookings | Medium | Yes | | cap:caldiy:booking.reschedule | POST /v2/bookings/{bookinguid}/reschedule | High | Yes | | cap:caldiy:booking.location.update | PATCH /v2/bookings/{bookinguid}/location | Medium | No | Change booking state or ownership | Capability | Provider request | Risk | Plan required | | cap:caldiy:booking.cancel | POST /v2/bookings/{bookinguid}/cancel | High | Yes | | cap:caldiy:booking.confirm | POST /v2/bookings/{bookinguid}/confirm | High | No | | cap:caldiy:booking.decline | POST /v2/bookings/{bookinguid}/decline | High | No | | cap:caldiy:booking.markabsent | POST /v2/bookings/{bookinguid}/mark-absent | High | No | | cap:caldiy:booking.reassign | POST /v2/bookings/{bookinguid}/reassign | High | No | | cap:caldiy:booking.reassigntouser | POST /v2/bookings/{bookinguid}/reassign/{userid} | High | No | Every mutation requires approval and an idempotency key even when the table does not require a transaction plan. List bookings cap:caldiy:booking.list accepts an empty object or any supported filter: | Field | Constraint | | status | Non-empty unique array of upcoming, recurring, past, cancelled, or unconfirmed | | attendeeEmail | Email string | | attendeeName | String | | bookingUid | Non-empty string | | eventTypeIds | Non-empty array of integers | | eventTypeId | Integer | | teamsIds | Non-empty array of integers | | teamId | Integer | | afterStart, beforeEnd | Date-time strings | | afterCreatedAt, beforeCreatedAt | Date-time strings | | afterUpdatedAt, beforeUpdatedAt | Date-time strings | | sortStart, sortEnd | asc or desc | | sortCreated, sortUpdatedAt | asc or desc | | take | Integer from 1 through 250 | | skip | Integer at least 0 | Additional fields are rejected. The connector encodes these values as query parameters. It does not add logical constraints between overlapping singular and plural filters; Cal.diy can reject or further interpret a schema-valid combination. Example: { "status": ["upcoming", "unconfirmed"], "afterStart": "2030-01-01T00:00:00Z", "beforeEnd": "2030-02-01T00:00:00Z", "sortStart": "asc", "take": 50, "skip": 0 } Read by booking or seat uid Read a regular or recurring booking set with: { "bookinguid": "booking-provider-uid" } Read a seated booking with: { "seatuid": "seat-provider-uid" } Both bookinguid and seatuid must be non-empty strings. Treat them as sensitive external handles. The connector percent-encodes them into provider paths, so keep raw values out of application logs, user-visible URLs, and metric labels. The three read capabilities are synchronous, low risk, retry-safe, and eligible for connector retry. Their idempotency key is optional and action-scoped. They still require authenticated account routing and restricted-data policy. Create a booking cap:caldiy:booking.create requires start, attendee, and exactly one event-type selector. A minimal id-based input is: { "start": "2030-01-03T10:00:00Z", "eventTypeId": 42, "attendee": { "name": "Avery Patel", "email": "avery@example.com", "timeZone": "Europe/London" } } Event-type selectors Choose exactly one branch: | Branch | Required fields | Optional related field | | Provider id | eventTypeId | None | | User-owned slug | eventTypeSlug, username | organizationSlug | | Team-owned slug | eventTypeSlug, teamSlug | organizationSlug | The id is an integer. Slugs and usernames must be non-empty strings. Satisfying more than one branch makes the oneOf input invalid. Do not mix selector fields even when an incomplete second branch could still pass the schema. Attendee attendee requires a non-empty name, a non-empty timeZone, and at least one of email or phoneNumber: | Field | Constraint | | name | Non-empty string | | timeZone | Non-empty string | | email | Email string; required when phone is absent | | phoneNumber | + plus 7 through 15 digits; required when email is absent | | language | The 43-value Cal.diy locale enum | The locale enum is the same source-owned set listed in the profile capability reference (profile.md). Additional attendee fields are rejected. Optional booking fields | Field | Constraint or role | | bookingFieldsResponses | Object with provider-defined response keys and values | | guests | Unique array of email strings | | meetingUrl | URI string; deprecated | | location | One supported create-location variant | | metadata | At most 46 application entries; string values only | | lengthInMinutes | Integer at least 1 | | routing | Routing-form response and team-member selection | | emailVerificationCode | String | | recurrenceCount | Integer at least 1 | metadata property names have at most 40 characters and values have at most 500 characters. The connector reserves and writes these keys before provider dispatch: • aipactionid; • aipoperationid; • aipidempotencyhash; • aiptransactionid when a transaction id exists. The idempotency value is hashed before insertion. Do not supply those reserved keys as application metadata; connector values overwrite matching keys. routing requires integer responseId and an array of integer teamMemberIds. It may also contain teamMemberEmail, skipContactOwner, crmAppSlug, and crmOwnerRecordType. Additional routing fields are rejected. Create locations Create accepts these object variants: | Type | Required value | | integration | One of the 29 supported integration names | | attendeeAddress | Non-empty address | | attendeePhone | E.164-like phone | | attendeeDefined | Non-empty location | | address, link, phone, organizersDefaultApp | Type discriminator only | The integration enum is listed in the event-type capability reference (event-types-and-private-links.md). A non-empty free-form string is also accepted for compatibility but is marked deprecated. Do not introduce new use of the deprecated string or meetingUrl. Plan booking creation Booking create cannot use the direct invocation path. The connector returns connector.caldiy.transactionrequired until the action follows the AIP plan and commit lifecycle. The plan: 1. validates the exact create input; 2. queries slot.list from the requested start through one day later; 3. requests time format; 4. verifies that the response contains the exact requested date-time start; 5. returns a completed plan result without committing a provider side effect. The plan result identifies the operation, API version, provider path, input hash, validation class downstreamslotavailability, and sideeffectcommitted: false. A passing plan is an observation, not a reservation. Availability can change before commit. Reviewed planner limitation At the reviewed source revision, the slot probe forwards eventTypeId, eventTypeSlug, username, organizationSlug, timeZone, and a field named duration when present. The create schema exposes teamSlug, nested attendee.timeZone, and lengthInMinutes; it does not accept top-level timeZone or duration. Consequently, the planner does not forward a team selector's teamSlug or a custom lengthInMinutes or attendee time zone into the provider availability query. It checks only whether the requested start appears in the returned slots. Treat team-slug, custom-length, and time-zone plan coverage as an implementation limitation at this revision; do not describe it as full downstream validation. Reschedule a booking Reschedule requires a booking uid and new start: { "bookinguid": "booking-provider-uid", "start": "2030-01-03T11:00:00Z", "rescheduledBy": "operator@example.com", "reschedulingReason": "Customer requested a later time" } Optional fields are rescheduledBy as an email, reschedulingReason as a string, non-empty seatUid, and emailVerificationCode as a string. For a seat-specific reschedule, include seatUid and omit reschedulingReason. The schema rejects an input containing both. A regular reschedule omits seatUid and may include the reason. Reschedule is high risk and requires plan before commit. Its plan reads the booking, requires integer /data/eventTypeId in the provider result, queries availability for that event type while passing the booking uid as bookingUidToReschedule, and checks the exact requested start. The plan's validation class is bookingstateanddownstreamslotavailability. If the booking result omits data.eventTypeId, planning fails before the reschedule request. A passing plan still does not reserve the new slot. Cancel a booking Cancel requires the booking uid: { "bookinguid": "booking-provider-uid", "cancellationReason": "Customer cancelled", "cancelSubsequentBookings": true } For a seat-specific cancellation, include non-empty seatUid and omit cancelSubsequentBookings. The schema rejects both fields together. cancellationReason remains optional in either branch. Cancel is a high-risk destructive mutation and requires plan before commit. Its plan reads the target booking and returns validation class downstreamtargetexists. It does not simulate cancellation or prove that notifications will be delivered. Cancellation has no rollback. It is the named best-effort compensation for a booking create, but executing it cannot erase already delivered notifications, calendar observations, or other downstream effects. Confirm or decline a booking Confirm accepts only: { "bookinguid": "booking-provider-uid" } Decline optionally adds a reason: { "bookinguid": "booking-provider-uid", "reason": "Requested time cannot be supported" } Both are high risk. Confirm is not marked destructive; decline is. Neither requires a plan before commit, but both require approval and first read the target booking. Both carry the sendmessage side-effect marker. Mark absence Mark host absence, attendee absence, or both: { "bookinguid": "booking-provider-uid", "host": false, "attendees": [ { "email": "avery@example.com", "absent": true } ] } attendees must be non-empty when present. Each item requires an email and a Boolean absent; additional item fields are rejected. Only bookinguid is required by the schema, so an input with no host or attendees is schema-valid. Do not use an empty absence update as a probe; Cal.diy may reject it or apply provider-specific behavior. This high-risk mutation first reads the booking. It does not carry the connector's sendmessage marker. Reassign a booking Automatic round-robin reassignment accepts only the booking uid: { "bookinguid": "booking-provider-uid" } Reassignment to a selected user also requires an integer userid and may include a reason: { "bookinguid": "booking-provider-uid", "userid": 73, "reason": "Route to the account owner" } The connector puts both identifiers in the provider path and sends reason in the JSON body. Both operations are high risk, first read the booking, and do not carry the connector's sendmessage marker. Provider behavior may still affect calendars or notifications; the absence of that marker is not a delivery guarantee. Update the booking location Location update requires only the booking uid; include a location to make an intentional change: { "bookinguid": "booking-provider-uid", "location": { "type": "link", "link": "https://meet.example.com/room-42" } } Update accepts: • integration with one supported integration name; • attendeeAddress with non-empty address; • attendeePhone with E.164-like phone; • attendeeDefined with non-empty location; • address, link, or phone with the corresponding non-empty value. Unlike create, location update does not accept organizersDefaultApp, a bare deprecated string, or discriminator-only address, link, or phone. The schema permits omission of location. Do not send that empty update as a probe. This medium-risk mutation first reads the booking and does not carry the sendmessage marker. Preflight and planning matrix | Mutation | Read or validation before provider mutation | Plan required | | Create | Exact-start slot query | Yes | | Reschedule | Booking read, event-type extraction, exact-start slot query | Yes | | Cancel | Booking read | Yes | | Confirm | Booking read | No | | Decline | Booking read | No | | Mark absent | Booking read | No | | Reassign | Booking read | No | | Reassign to user | Booking read | No | | Location update | Booking read | No | A preflight detects some stale or missing targets before mutation. It does not reserve state, authorize the action, guarantee provider acceptance, or make a write safe to retry. Shared mutation contract The nine mutations require: • approval selected by tenant policy; • a 900,000 ms approval validity window; • reason, input snapshot, and policy-decision evidence; • an external-account-scoped idempotency key; • input-hash revalidation on key collision. All mutations are synchronous, advertise no connector retry, and are retry unsafe. Preserve the same key only for the same capability, account, and canonical input. Reconcile uncertain provider dispatch instead of creating a replacement key. Create, reschedule, cancel, confirm, and decline carry sendmessage in addition to write and external-network side effects. This marker means a provider operation may affect customer-visible notifications or connected calendar state; it does not prove delivery. All mutations advertise dryrun, plan, commit, and reconcile. Create, reschedule, and cancel require a validated plan and have downstream-validation dry-run fidelity. The remaining mutations have policy-and-schema fidelity and do not require plan before commit. Booking create names booking.cancel as best-effort compensation. The contract window is 24 hours and compensation requires approval. It is a new governed action, not an automatic or atomic rollback. Every other operation on this page has no compensating capability. Result and data contract The connector returns the validated provider JSON body as AIP output. It requires a non-empty string status; data, pagination, and additional provider fields are optional. The connector does not publish an exhaustive booking response schema. Before returning output, the connector recursively redacts fields whose normalized names identify secrets, API keys, or tokens. This targeted redaction does not declassify booking content. Inputs, outputs, approval snapshots, receipts, and diagnostic evidence remain restricted and PII-bearing. Failures and recovery | Failure | Relevant cause | Safe response | | connector.caldiy.transactionrequired | Create, reschedule, or cancel used direct invocation | Start the governed plan-and-commit lifecycle | | connector.caldiy.slotunavailable | Planned create or reschedule start is absent from current slots | Choose a new start and produce a new plan | | connector.caldiy.invalidaction | Schema mismatch or reschedule booking result omitted eventTypeId | Correct input or investigate provider response drift | | connector.caldiy.policy | Mutation omitted its idempotency key | Preserve approved input and supply the required key | | connector.caldiy.idempotencycollision | One key owns different canonical input | Stop and inspect the original action | | connector.caldiy.inflight | The matching mutation is executing | Read durable state and wait | | connector.caldiy.outcomeunknown | Prior provider dispatch cannot be proved | Reconcile; do not repeat the mutation | | connector.caldiy.authentication | Provider returned 401 or 403 | Verify account binding, credential revision, and booking ownership | | connector.caldiy.stateconflict | Provider returned 409 or 412 | Read current booking state and reconsider the transition | | 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 | Provider success lacked a valid status | Preserve evidence and reconcile a mutation | | connector.caldiy.reconciliationnotfound | Durable provider operation cannot be found | Stop and escalate with the original action and operation ids | Permanent provider 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 a booking transition For every operation, retain the capability id, tenant and external account, AIP action id, input hash, provider request id when present, and completed or reconciled durable state. For create, reschedule, or cancel, additionally verify the plan id and the exact input bound to it. For create, confirm the provider booking uid before using it in later actions. For state transitions, read the booking after a completed result and compare only the intended fields. Do not use a follow-up read to justify replaying an uncertain mutation. Resolve the original provider operation through reconciliation and retain the evidence strength of that result. These checks validate application handling. They do not establish live Cal.diy qualification or production readiness for a specific deployment. Related documentation • Cal.diy capability index (README.md) • Slots and reservations (slots-and-reservations.md) • Booking attendees and artifacts (booking-attendees-and-artifacts.md) • Approvals and policy (../../../concepts/approvals-and-policy.md) • Transactions and compensation (../../../concepts/transactions-and-compensation.md)