{
  "schemaVersion": "1.0",
  "title": "Diagnose Cal.diy availability and calendar conflicts",
  "description": "Use this guide when an expected Cal.diy slot is missing or when you need to change the schedule or calendars that can contribute conflicts. You will capture one repeatable baseline, change at most one input layer, and compare the same obser",
  "canonical": "https://getaip.org/docs/connectors/cal-diy/guides/availability-and-calendar-conflicts",
  "route": "/docs/connectors/cal-diy/guides/availability-and-calendar-conflicts",
  "source": "docs/connectors/cal-diy/guides/availability-and-calendar-conflicts.md",
  "protocol": "Agent Interoperability Protocol",
  "protocolVersion": "1.0",
  "section": "Connectors",
  "documentType": "Connector",
  "language": "en",
  "downloads": {
    "md": "/docs/download/connectors/cal-diy/guides/availability-and-calendar-conflicts.md",
    "txt": "/docs/download/connectors/cal-diy/guides/availability-and-calendar-conflicts.txt",
    "json": "/docs/download/connectors/cal-diy/guides/availability-and-calendar-conflicts.json",
    "pdf": "/docs/download/connectors/cal-diy/guides/availability-and-calendar-conflicts.pdf"
  },
  "content": {
    "format": "text/markdown",
    "markdown": "---\ntitle: Diagnose Cal.diy availability and calendar conflicts\ndescription: Separate schedule, busy-time, conflict-calendar, and slot evidence before changing availability\nkind: how-to\naudience: application-developer\nappliesTo: \"1.x\"\nwritingStandard: \"aip-docs/1.0\"\nlastReviewedRevision: \"97be86e9efedf07ecf1783b03800f683f107fb04\"\nconnector: cal-diy\n---\n\n# Diagnose Cal.diy availability and calendar conflicts\n\nUse this guide when an expected Cal.diy slot is missing or when you need to\nchange the schedule or calendars that can contribute conflicts. You will\ncapture one repeatable baseline, change at most one input layer, and compare the\nsame observations afterward.\n\nThe connector exposes the relevant reads and mutations, but it does not expose\nan operation that explains why Cal.diy returned or omitted a slot. Treat the\nresult as evidence at one time, not as a causal diagnosis or a capacity hold.\n\n## Keep the six layers separate\n\nAvailability is not one connector object. Record which layer each observation\nor change belongs to:\n\n| Layer | What it can show or change | What it does not prove |\n|---|---|---|\n| Event type | `scheduleId`, booking window, notice, duration, and buffers in provider-owned state | That the linked schedule or every rule is valid |\n| Schedule | Weekly intervals and dated overrides owned by one schedule | That the event type uses this schedule |\n| Conflict selection | Which external calendars Cal.diy should consider | The events or busy intervals on those calendars |\n| Busy/free-busy | Explicit intervals returned for an exact account, range, and calendar set | That Cal.diy used the same set to calculate slots |\n| Slots | Provider availability for one selector, range, and query shape | A reservation or the reason for a missing time |\n| Booking plan | Exact-start validation for one booking intent | General availability or a capacity hold |\n\nDo not substitute one layer for another. In particular, an empty busy result is\nnot a slot result, and a slot result does not reveal the selected conflict\ncalendar configuration.\n\n## Prerequisites\n\nYou need:\n\n- an admitted and healthy Cal.diy connector for the intended tenant;\n- a native AIP endpoint and token already bound to that tenant;\n- the integer id of one event type and one trusted schedule id;\n- the external calendar id, integration name, and credential id when inspecting\n  busy time or changing conflict selection;\n- a trusted tenant-policy approval path for mutations;\n- durable storage for action ids, mutation idempotency keys, results, and\n  provider request identifiers.\n\nSet the client coordinates without putting a provider credential in the shell:\n\n```sh\nexport AIP_URL='https://aip.example.com'\nexport AIP_TOKEN_FILE='/run/secrets/aip-native-token'\n```\n\nThe authenticated deployment context selects the tenant, external account,\nconnector route, and provider credential. Do not add those routing values to\nthe Cal.diy action input.\n\n## 1. Confirm the admitted contracts\n\nInspect the exact capabilities before using them:\n\n```sh\nfor capability in \\\n  cap:cal_diy:event_type.get \\\n  cap:cal_diy:schedule.get \\\n  cap:cal_diy:schedule.update \\\n  cap:cal_diy:calendar.list \\\n  cap:cal_diy:calendar.busy_time.list \\\n  cap:cal_diy:calendar.selected.add \\\n  cap:cal_diy:calendar.selected.delete \\\n  cap:cal_diy:slot.list\ndo\n  aipctl \\\n    --native-bearer-token-file \"$AIP_TOKEN_FILE\" \\\n    capability list \"$AIP_URL\" \\\n    --capability-id \"$capability\" \\\n    --limit 1\ndone\n```\n\nRecord the catalog revision and schema and contract digests. Confirm that the\nreads are low risk and approval-free. `schedule.update` and\n`calendar.selected.add` are medium risk; `calendar.selected.delete` is high\nrisk and destructive. All three mutations require tenant-policy approval and\nan external-account-scoped idempotency key.\n\nThese mutations do not require a downstream plan before commit. Their contract\nadvertises policy-and-schema dry-run fidelity. A transaction plan may perform\nthe operation's preflight read, but it does not calculate future slots or lock\nprovider state.\n\n## 2. Freeze one diagnostic scope\n\nWrite down one scope before making any call:\n\n| Coordinate | Example | Keep fixed because |\n|---|---|---|\n| Event type | `42` | A different selector can use different rules |\n| Schedule | `41` | Schedule reads do not prove event-type linkage |\n| Range | `2030-01-03` to `2030-01-04` | A changed interval produces a different observation |\n| Time zone | `Europe/London` | Local-time interpretation can change returned times |\n| Calendar | Credential `42`, `team@example.com` | Busy reads require an explicit calendar set |\n| Slot format | `time` | A changed format can change result representation |\n\nUse the same tenant and external account for the full investigation. If any\ncoordinate changes, start a new comparison instead of treating the result as\nthe after-state of this one.\n\n## 3. Read the event type and schedule\n\nWrite `event-type-get.json`:\n\n```json\n{\n  \"event_type_id\": 42\n}\n```\n\nRead the event type:\n\n```sh\nexport EVENT_TYPE_ACTION_ID='act_cal_availability_event_type_001'\n\naipctl \\\n  --native-bearer-token-file \"$AIP_TOKEN_FILE\" \\\n  action call \"$AIP_URL\" \\\n  cap:cal_diy:event_type.get \\\n  --action-id \"$EVENT_TYPE_ACTION_ID\" \\\n  --mode sync \\\n  --input @event-type-get.json\n```\n\nInspect the actual provider output for timing controls such as `scheduleId`,\n`minimumBookingNotice`, `beforeEventBuffer`, `afterEventBuffer`,\n`lengthInMinutes`, and booking-window values. The connector's common output\nschema does not guarantee those fields, so absence is not a default value.\n\nWrite `schedule-get.json`:\n\n```json\n{\n  \"schedule_id\": 41\n}\n```\n\nRead the schedule selected for this investigation:\n\n```sh\nexport SCHEDULE_ACTION_ID='act_cal_availability_schedule_001'\n\naipctl \\\n  --native-bearer-token-file \"$AIP_TOKEN_FILE\" \\\n  action call \"$AIP_URL\" \\\n  cap:cal_diy:schedule.get \\\n  --action-id \"$SCHEDULE_ACTION_ID\" \\\n  --mode sync \\\n  --input @schedule-get.json\n```\n\nRecord its time zone, weekly availability, dated overrides, and provider\nidentifier when present. Compare the returned id with the event type's actual\n`scheduleId` value. Do not assume that `SCHEDULE_ID` is linked merely because\nthe schedule exists.\n\nThe schedule schema checks field shapes, but not interval ordering, overlap,\ntime-zone validity, or daylight-saving behavior.\n\n## 4. Capture the baseline slot result\n\nWrite `slot-baseline.json` with one selector and the frozen range:\n\n```json\n{\n  \"start\": \"2030-01-03\",\n  \"end\": \"2030-01-04\",\n  \"eventTypeId\": 42,\n  \"timeZone\": \"Europe/London\",\n  \"format\": \"time\"\n}\n```\n\nRun the baseline read and retain its complete result and observation time:\n\n```sh\nexport BASELINE_SLOT_ACTION_ID='act_cal_availability_slots_before_001'\n\naipctl \\\n  --native-bearer-token-file \"$AIP_TOKEN_FILE\" \\\n  action call \"$AIP_URL\" \\\n  cap:cal_diy:slot.list \\\n  --action-id \"$BASELINE_SLOT_ACTION_ID\" \\\n  --mode sync \\\n  --input @slot-baseline.json\n```\n\nThe slot operation checks that `start` and `end` have ISO date or date-time\nshape, but it does not prove chronological order or validate the time-zone\nname. A completed result reports Cal.diy's response at that request boundary.\nIt does not reserve a returned time.\n\n## 5. Inspect explicit busy intervals\n\nFirst list the calendars visible through the current account route. Save an\nempty object as `calendar-list.json`:\n\n```json\n{}\n```\n\nRun the calendar read:\n\n```sh\nexport CALENDAR_LIST_ACTION_ID='act_cal_availability_calendars_001'\n\naipctl \\\n  --native-bearer-token-file \"$AIP_TOKEN_FILE\" \\\n  action call \"$AIP_URL\" \\\n  cap:cal_diy:calendar.list \\\n  --action-id \"$CALENDAR_LIST_ACTION_ID\" \\\n  --mode sync \\\n  --input @calendar-list.json\n```\n\nValidate the intended credential and external calendar against the actual\nprovider response when those fields are present. The common connector output\nschema does not guarantee their shape, and this operation is not a dedicated\nselected-conflict-calendar read.\n\nWrite `busy-time.json`:\n\n```json\n{\n  \"timeZone\": \"Europe/London\",\n  \"dateFrom\": \"2030-01-03\",\n  \"dateTo\": \"2030-01-04\",\n  \"calendarsToLoad\": [\n    {\n      \"credentialId\": 42,\n      \"externalId\": \"team@example.com\"\n    }\n  ]\n}\n```\n\nRead busy time for exactly that calendar set:\n\n```sh\nexport BUSY_ACTION_ID='act_cal_availability_busy_001'\n\naipctl \\\n  --native-bearer-token-file \"$AIP_TOKEN_FILE\" \\\n  action call \"$AIP_URL\" \\\n  cap:cal_diy:calendar.busy_time.list \\\n  --action-id \"$BUSY_ACTION_ID\" \\\n  --mode sync \\\n  --input @busy-time.json\n```\n\nEach `calendarsToLoad` object requires an integer `credentialId` and non-empty\n`externalId`. The connector encodes the array as nested query parameters. It\ndoes not infer the selected conflict-calendar set for you.\n\nCalendar reads are restricted, PII-bearing data. Store event details, external\nids, busy intervals, and results under the deployment's restricted-data policy.\n\n## 6. Choose one change, if any\n\nUse the evidence to choose one next action:\n\n| Observation | Next check or change | Do not conclude |\n|---|---|---|\n| Event type points to another schedule | Read that exact schedule before changing anything | The schedule you first read controls this event type |\n| Weekly interval or dated override excludes the time | Review one schedule patch | That a patch alone will create a slot |\n| Notice, buffer, duration, or booking window excludes the time | Review the event-type capability reference | That the calendar is the cause |\n| Explicit busy interval overlaps the expected time | Confirm the calendar identity and provider event | That it is selected for conflict detection |\n| Calendar should contribute conflicts but is not configured | Review one selected-calendar add | That `calendar.list` proves selection state |\n| All inspected inputs appear compatible | Preserve evidence and escalate provider-side diagnosis | That a missing connector explanation is proof of no conflict |\n\nChange at most one layer before repeating the reads. This makes the comparison\nuseful, but it still cannot establish provider causality.\n\n## 7. Update one schedule field safely\n\nSkip this step if the schedule is already correct. Use an id returned by a\ntrusted read and include an intentional patch field. For example, write\n`schedule-update.json`:\n\n```json\n{\n  \"schedule_id\": 41,\n  \"availability\": [\n    {\n      \"days\": [\"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\"],\n      \"startTime\": \"09:00\",\n      \"endTime\": \"17:00\"\n    }\n  ]\n}\n```\n\nReview the complete desired array before approval. The connector does not\ndefine whether Cal.diy merges or replaces availability arrays.\n\nUse one stable action id and idempotency key:\n\n```sh\nexport SCHEDULE_UPDATE_ACTION_ID='act_cal_availability_schedule_update_001'\nexport SCHEDULE_UPDATE_KEY='cal-availability-schedule-update-001'\n\naipctl \\\n  --native-bearer-token-file \"$AIP_TOKEN_FILE\" \\\n  action call \"$AIP_URL\" \\\n  cap:cal_diy:schedule.update \\\n  --action-id \"$SCHEDULE_UPDATE_ACTION_ID\" \\\n  --idempotency-key \"$SCHEDULE_UPDATE_KEY\" \\\n  --input @schedule-update.json\n```\n\nThe connector performs an exact schedule read before dispatch. That preflight\nis not a lock and does not validate the new intervals. A trusted approver must\nreview the input snapshot and policy evidence. Approval resumes the same action;\ndo not submit a replacement action while it is waiting.\n\n`schedule.update` accepts a string or integer id, although schedule get and\ndelete accept only an integer. Use the integer returned by the trusted read.\nUpdate has no compensating capability.\n\n## 8. Add one conflict calendar safely\n\nSkip this step if conflict selection is not the intended change. Write\n`conflict-calendar-add.json`:\n\n```json\n{\n  \"integration\": \"google_calendar\",\n  \"externalId\": \"team@example.com\",\n  \"credentialId\": 42\n}\n```\n\nUse the exact external id and integer credential id reviewed in the current\naccount route:\n\n```sh\nexport CALENDAR_ADD_ACTION_ID='act_cal_availability_calendar_add_001'\nexport CALENDAR_ADD_KEY='cal-availability-calendar-add-001'\n\naipctl \\\n  --native-bearer-token-file \"$AIP_TOKEN_FILE\" \\\n  action call \"$AIP_URL\" \\\n  cap:cal_diy:calendar.selected.add \\\n  --action-id \"$CALENDAR_ADD_ACTION_ID\" \\\n  --idempotency-key \"$CALENDAR_ADD_KEY\" \\\n  --input @conflict-calendar-add.json\n```\n\nThe connector lists calendars before dispatch, but it does not verify that the\nrequested `externalId` appeared in that result. Provider validation still owns\nthe mutation decision.\n\nThe add contract names `calendar.selected.delete` as best-effort compensation\nwithin 24 hours. Compensation is a separate, approval-required destructive\naction. The declaration does not transform add input into valid delete input;\ndelete requires the credential id as a string.\n\n## 9. Wait for the original mutation\n\nFor the one mutation you submitted, read the same action until it reaches a\nterminal state. For a schedule update:\n\n```sh\naipctl \\\n  --native-bearer-token-file \"$AIP_TOKEN_FILE\" \\\n  action status \"$AIP_URL\" \\\n  \"$SCHEDULE_UPDATE_ACTION_ID\" \\\n  --include-result \\\n  --include-receipts \\\n  --wait-ms 30000\n```\n\nUse `CALENDAR_ADD_ACTION_ID` instead if you added a conflict calendar. Preserve\nthe approval evidence, original input, idempotency key, provider request id,\nand provider operation id when present.\n\nOnly a terminal `completed` result proves that the connector accepted the\nprovider response and durably settled the action. It does not prove immediate\navailability propagation.\n\n## 10. Repeat the same observations\n\nAfter a completed mutation:\n\n1. read the same event type again;\n2. read the same schedule again after a schedule change;\n3. list calendars again after a selected-calendar change;\n4. repeat `busy-time.json` if busy evidence remains relevant;\n5. submit the unchanged `slot-baseline.json` under a new action id.\n\nRepeat the slot query without editing its selector, range, time zone, or format:\n\n```sh\nexport AFTER_SLOT_ACTION_ID='act_cal_availability_slots_after_001'\n\naipctl \\\n  --native-bearer-token-file \"$AIP_TOKEN_FILE\" \\\n  action call \"$AIP_URL\" \\\n  cap:cal_diy:slot.list \\\n  --action-id \"$AFTER_SLOT_ACTION_ID\" \\\n  --mode sync \\\n  --input @slot-baseline.json\n```\n\nCompare the before and after provider payloads and their observation times. A\nchanged result is correlated with the controlled change; it is not a connector\nexplanation of cause. An unchanged result can reflect another availability\nlayer, provider propagation, or provider-owned behavior.\n\n## Remove a conflict calendar safely\n\nRemoval is not an exploratory diagnostic step. Use it only when the intended\nstate is to stop considering a known calendar and you have authoritative values\nfor every selector.\n\nWrite `conflict-calendar-delete.json`. Note that `credentialId` is a string:\n\n```json\n{\n  \"integration\": \"google_calendar\",\n  \"externalId\": \"team@example.com\",\n  \"credentialId\": \"42\"\n}\n```\n\nSubmit the destructive operation with a new stable identity:\n\n```sh\nexport CALENDAR_DELETE_ACTION_ID='act_cal_availability_calendar_delete_001'\nexport CALENDAR_DELETE_KEY='cal-availability-calendar-delete-001'\n\naipctl \\\n  --native-bearer-token-file \"$AIP_TOKEN_FILE\" \\\n  action call \"$AIP_URL\" \\\n  cap:cal_diy:calendar.selected.delete \\\n  --action-id \"$CALENDAR_DELETE_ACTION_ID\" \\\n  --idempotency-key \"$CALENDAR_DELETE_KEY\" \\\n  --input @conflict-calendar-delete.json\n```\n\nThe client sends every supplied supported field as a `DELETE` query parameter:\n`integration`, `externalId`, `credentialId`, and optional\n`delegationCredentialId`. Removal is high risk, approval-required,\nretry-unsafe, and has no rollback contract. Adding a calendar later is a new\nmutation, not restoration of the deleted provider state.\n\n## Diagnose a missing slot\n\nUse this table after preserving the baseline:\n\n| Check | Evidence to compare | Safe next action |\n|---|---|---|\n| Event-type linkage | Actual `scheduleId` in provider output | Read that exact schedule |\n| Weekly availability | Day and local start/end for the frozen range | Correct one reviewed interval if wrong |\n| Dated override | Override date and local interval | Correct one override if wrong |\n| Booking limits | Window, notice, duration, offset, and buffers | Review event-type configuration |\n| Conflict selection | Exact integration, external id, and credential id | Add only the intended calendar |\n| Busy time | Exact calendar set, range, time zone, and intervals | Inspect the overlapping provider event |\n| Slot query | One selector branch, range, time zone, duration, and format | Correct the query and create a new baseline |\n| Booking plan | Exact requested start and documented planner limits | Use it only for the final booking intent |\n| Provider state | Credential health, response status, request id, and time | Escalate with retained evidence |\n\nThe connector publishes no selected-calendar-specific read and no\navailability-explanation capability. If the remaining question requires either\none, report that evidence gap instead of inventing a reason from nearby data.\n\n## Recover without replaying a mutation\n\n| State or failure | Safe response |\n|---|---|\n| `requires_human` | Complete trusted approval for the same action or let it expire |\n| `in_flight` | Read durable status and wait; keep the same action and key |\n| `outcome_unknown` | Reconcile the original provider operation; do not send a new key |\n| Transport failure after possible dispatch | Treat the mutation as uncertain and reconcile |\n| Authentication failure | Verify tenant, external-account binding, and credential revision |\n| Provider conflict | Refresh the exact schedule or calendar evidence before reviewing a new intent |\n| Rate limit or temporary provider failure on a read | Retry the read within deadline and policy |\n| Invalid action | Correct the input and use a new action for the corrected intent |\n| Idempotency collision | Stop; one key already owns different canonical input |\n\nConnector retries are supported for the reads in this guide, but not for its\nmutations. Never use a new action id or idempotency key merely to escape an\nuncertain mutation state.\n\n## Evidence checklist\n\nRetain:\n\n- catalog revision and capability schema and contract digests;\n- tenant and external-account route, without copying provider credentials;\n- frozen event-type, schedule, range, time zone, calendar, and slot coordinates;\n- before and after event-type, schedule, calendar, busy-time, and slot results;\n- action ids, one mutation idempotency key, approval evidence, and receipts;\n- provider request and operation identifiers when present;\n- observation times and any reported propagation or response-shape gap.\n\nThis evidence supports a bounded comparison. It does not prove live connector\nqualification, provider causality, future bookability, or successful booking.\n\n## Related documentation\n\n- [Slots and reservations](../capabilities/slots-and-reservations.md)\n- [Calendars and free/busy](../capabilities/calendars-and-free-busy.md)\n- [Schedules](../capabilities/schedules.md)\n- [Event types and private links](../capabilities/event-types-and-private-links.md)\n- [Error reference](../../../reference/errors.md)\n",
    "text": "Diagnose Cal.diy availability and calendar conflicts\n\nUse this guide when an expected Cal.diy slot is missing or when you need to\nchange the schedule or calendars that can contribute conflicts. You will\ncapture one repeatable baseline, change at most one input layer, and compare the\nsame observations afterward.\n\nThe connector exposes the relevant reads and mutations, but it does not expose\nan operation that explains why Cal.diy returned or omitted a slot. Treat the\nresult as evidence at one time, not as a causal diagnosis or a capacity hold.\n\nKeep the six layers separate\n\nAvailability is not one connector object. Record which layer each observation\nor change belongs to:\n\n| Layer | What it can show or change | What it does not prove |\n\n| Event type | scheduleId, booking window, notice, duration, and buffers in provider-owned state | That the linked schedule or every rule is valid |\n| Schedule | Weekly intervals and dated overrides owned by one schedule | That the event type uses this schedule |\n| Conflict selection | Which external calendars Cal.diy should consider | The events or busy intervals on those calendars |\n| Busy/free-busy | Explicit intervals returned for an exact account, range, and calendar set | That Cal.diy used the same set to calculate slots |\n| Slots | Provider availability for one selector, range, and query shape | A reservation or the reason for a missing time |\n| Booking plan | Exact-start validation for one booking intent | General availability or a capacity hold |\n\nDo not substitute one layer for another. In particular, an empty busy result is\nnot a slot result, and a slot result does not reveal the selected conflict\ncalendar configuration.\n\nPrerequisites\n\nYou need:\n• an admitted and healthy Cal.diy connector for the intended tenant;\n• a native AIP endpoint and token already bound to that tenant;\n• the integer id of one event type and one trusted schedule id;\n• the external calendar id, integration name, and credential id when inspecting\n  busy time or changing conflict selection;\n• a trusted tenant-policy approval path for mutations;\n• durable storage for action ids, mutation idempotency keys, results, and\n  provider request identifiers.\n\nSet the client coordinates without putting a provider credential in the shell:\n\nexport AIPURL='https://aip.example.com'\nexport AIPTOKENFILE='/run/secrets/aip-native-token'\n\nThe authenticated deployment context selects the tenant, external account,\nconnector route, and provider credential. Do not add those routing values to\nthe Cal.diy action input.\n1. Confirm the admitted contracts\n\nInspect the exact capabilities before using them:\n\nfor capability in \\\n  cap:caldiy:eventtype.get \\\n  cap:caldiy:schedule.get \\\n  cap:caldiy:schedule.update \\\n  cap:caldiy:calendar.list \\\n  cap:caldiy:calendar.busytime.list \\\n  cap:caldiy:calendar.selected.add \\\n  cap:caldiy:calendar.selected.delete \\\n  cap:caldiy:slot.list\ndo\n  aipctl \\\n    --native-bearer-token-file \"$AIPTOKENFILE\" \\\n    capability list \"$AIPURL\" \\\n    --capability-id \"$capability\" \\\n    --limit 1\ndone\n\nRecord the catalog revision and schema and contract digests. Confirm that the\nreads are low risk and approval-free. schedule.update and\ncalendar.selected.add are medium risk; calendar.selected.delete is high\nrisk and destructive. All three mutations require tenant-policy approval and\nan external-account-scoped idempotency key.\n\nThese mutations do not require a downstream plan before commit. Their contract\nadvertises policy-and-schema dry-run fidelity. A transaction plan may perform\nthe operation's preflight read, but it does not calculate future slots or lock\nprovider state.\n2. Freeze one diagnostic scope\n\nWrite down one scope before making any call:\n\n| Coordinate | Example | Keep fixed because |\n\n| Event type | 42 | A different selector can use different rules |\n| Schedule | 41 | Schedule reads do not prove event-type linkage |\n| Range | 2030-01-03 to 2030-01-04 | A changed interval produces a different observation |\n| Time zone | Europe/London | Local-time interpretation can change returned times |\n| Calendar | Credential 42, team@example.com | Busy reads require an explicit calendar set |\n| Slot format | time | A changed format can change result representation |\n\nUse the same tenant and external account for the full investigation. If any\ncoordinate changes, start a new comparison instead of treating the result as\nthe after-state of this one.\n3. Read the event type and schedule\n\nWrite event-type-get.json:\n\n{\n  \"eventtypeid\": 42\n}\n\nRead the event type:\n\nexport EVENTTYPEACTIONID='actcalavailabilityeventtype001'\n\naipctl \\\n  --native-bearer-token-file \"$AIPTOKENFILE\" \\\n  action call \"$AIPURL\" \\\n  cap:caldiy:eventtype.get \\\n  --action-id \"$EVENTTYPEACTIONID\" \\\n  --mode sync \\\n  --input @event-type-get.json\n\nInspect the actual provider output for timing controls such as scheduleId,\nminimumBookingNotice, beforeEventBuffer, afterEventBuffer,\nlengthInMinutes, and booking-window values. The connector's common output\nschema does not guarantee those fields, so absence is not a default value.\n\nWrite schedule-get.json:\n\n{\n  \"scheduleid\": 41\n}\n\nRead the schedule selected for this investigation:\n\nexport SCHEDULEACTIONID='actcalavailabilityschedule001'\n\naipctl \\\n  --native-bearer-token-file \"$AIPTOKENFILE\" \\\n  action call \"$AIPURL\" \\\n  cap:caldiy:schedule.get \\\n  --action-id \"$SCHEDULEACTIONID\" \\\n  --mode sync \\\n  --input @schedule-get.json\n\nRecord its time zone, weekly availability, dated overrides, and provider\nidentifier when present. Compare the returned id with the event type's actual\nscheduleId value. Do not assume that SCHEDULEID is linked merely because\nthe schedule exists.\n\nThe schedule schema checks field shapes, but not interval ordering, overlap,\ntime-zone validity, or daylight-saving behavior.\n4. Capture the baseline slot result\n\nWrite slot-baseline.json with one selector and the frozen range:\n\n{\n  \"start\": \"2030-01-03\",\n  \"end\": \"2030-01-04\",\n  \"eventTypeId\": 42,\n  \"timeZone\": \"Europe/London\",\n  \"format\": \"time\"\n}\n\nRun the baseline read and retain its complete result and observation time:\n\nexport BASELINESLOTACTIONID='actcalavailabilityslotsbefore001'\n\naipctl \\\n  --native-bearer-token-file \"$AIPTOKENFILE\" \\\n  action call \"$AIPURL\" \\\n  cap:caldiy:slot.list \\\n  --action-id \"$BASELINESLOTACTIONID\" \\\n  --mode sync \\\n  --input @slot-baseline.json\n\nThe slot operation checks that start and end have ISO date or date-time\nshape, but it does not prove chronological order or validate the time-zone\nname. A completed result reports Cal.diy's response at that request boundary.\nIt does not reserve a returned time.\n5. Inspect explicit busy intervals\n\nFirst list the calendars visible through the current account route. Save an\nempty object as calendar-list.json:\n\n{}\n\nRun the calendar read:\n\nexport CALENDARLISTACTIONID='actcalavailabilitycalendars001'\n\naipctl \\\n  --native-bearer-token-file \"$AIPTOKENFILE\" \\\n  action call \"$AIPURL\" \\\n  cap:caldiy:calendar.list \\\n  --action-id \"$CALENDARLISTACTIONID\" \\\n  --mode sync \\\n  --input @calendar-list.json\n\nValidate the intended credential and external calendar against the actual\nprovider response when those fields are present. The common connector output\nschema does not guarantee their shape, and this operation is not a dedicated\nselected-conflict-calendar read.\n\nWrite busy-time.json:\n\n{\n  \"timeZone\": \"Europe/London\",\n  \"dateFrom\": \"2030-01-03\",\n  \"dateTo\": \"2030-01-04\",\n  \"calendarsToLoad\": [\n    {\n      \"credentialId\": 42,\n      \"externalId\": \"team@example.com\"\n    }\n  ]\n}\n\nRead busy time for exactly that calendar set:\n\nexport BUSYACTIONID='actcalavailabilitybusy001'\n\naipctl \\\n  --native-bearer-token-file \"$AIPTOKENFILE\" \\\n  action call \"$AIPURL\" \\\n  cap:caldiy:calendar.busytime.list \\\n  --action-id \"$BUSYACTIONID\" \\\n  --mode sync \\\n  --input @busy-time.json\n\nEach calendarsToLoad object requires an integer credentialId and non-empty\nexternalId. The connector encodes the array as nested query parameters. It\ndoes not infer the selected conflict-calendar set for you.\n\nCalendar reads are restricted, PII-bearing data. Store event details, external\nids, busy intervals, and results under the deployment's restricted-data policy.\n6. Choose one change, if any\n\nUse the evidence to choose one next action:\n\n| Observation | Next check or change | Do not conclude |\n\n| Event type points to another schedule | Read that exact schedule before changing anything | The schedule you first read controls this event type |\n| Weekly interval or dated override excludes the time | Review one schedule patch | That a patch alone will create a slot |\n| Notice, buffer, duration, or booking window excludes the time | Review the event-type capability reference | That the calendar is the cause |\n| Explicit busy interval overlaps the expected time | Confirm the calendar identity and provider event | That it is selected for conflict detection |\n| Calendar should contribute conflicts but is not configured | Review one selected-calendar add | That calendar.list proves selection state |\n| All inspected inputs appear compatible | Preserve evidence and escalate provider-side diagnosis | That a missing connector explanation is proof of no conflict |\n\nChange at most one layer before repeating the reads. This makes the comparison\nuseful, but it still cannot establish provider causality.\n7. Update one schedule field safely\n\nSkip this step if the schedule is already correct. Use an id returned by a\ntrusted read and include an intentional patch field. For example, write\nschedule-update.json:\n\n{\n  \"scheduleid\": 41,\n  \"availability\": [\n    {\n      \"days\": [\"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\"],\n      \"startTime\": \"09:00\",\n      \"endTime\": \"17:00\"\n    }\n  ]\n}\n\nReview the complete desired array before approval. The connector does not\ndefine whether Cal.diy merges or replaces availability arrays.\n\nUse one stable action id and idempotency key:\n\nexport SCHEDULEUPDATEACTIONID='actcalavailabilityscheduleupdate001'\nexport SCHEDULEUPDATEKEY='cal-availability-schedule-update-001'\n\naipctl \\\n  --native-bearer-token-file \"$AIPTOKENFILE\" \\\n  action call \"$AIPURL\" \\\n  cap:caldiy:schedule.update \\\n  --action-id \"$SCHEDULEUPDATEACTIONID\" \\\n  --idempotency-key \"$SCHEDULEUPDATEKEY\" \\\n  --input @schedule-update.json\n\nThe connector performs an exact schedule read before dispatch. That preflight\nis not a lock and does not validate the new intervals. A trusted approver must\nreview the input snapshot and policy evidence. Approval resumes the same action;\ndo not submit a replacement action while it is waiting.\n\nschedule.update accepts a string or integer id, although schedule get and\ndelete accept only an integer. Use the integer returned by the trusted read.\nUpdate has no compensating capability.\n8. Add one conflict calendar safely\n\nSkip this step if conflict selection is not the intended change. Write\nconflict-calendar-add.json:\n\n{\n  \"integration\": \"googlecalendar\",\n  \"externalId\": \"team@example.com\",\n  \"credentialId\": 42\n}\n\nUse the exact external id and integer credential id reviewed in the current\naccount route:\n\nexport CALENDARADDACTIONID='actcalavailabilitycalendaradd001'\nexport CALENDARADDKEY='cal-availability-calendar-add-001'\n\naipctl \\\n  --native-bearer-token-file \"$AIPTOKENFILE\" \\\n  action call \"$AIPURL\" \\\n  cap:caldiy:calendar.selected.add \\\n  --action-id \"$CALENDARADDACTIONID\" \\\n  --idempotency-key \"$CALENDARADDKEY\" \\\n  --input @conflict-calendar-add.json\n\nThe connector lists calendars before dispatch, but it does not verify that the\nrequested externalId appeared in that result. Provider validation still owns\nthe mutation decision.\n\nThe add contract names calendar.selected.delete as best-effort compensation\nwithin 24 hours. Compensation is a separate, approval-required destructive\naction. The declaration does not transform add input into valid delete input;\ndelete requires the credential id as a string.\n9. Wait for the original mutation\n\nFor the one mutation you submitted, read the same action until it reaches a\nterminal state. For a schedule update:\n\naipctl \\\n  --native-bearer-token-file \"$AIPTOKENFILE\" \\\n  action status \"$AIPURL\" \\\n  \"$SCHEDULEUPDATEACTIONID\" \\\n  --include-result \\\n  --include-receipts \\\n  --wait-ms 30000\n\nUse CALENDARADDACTIONID instead if you added a conflict calendar. Preserve\nthe approval evidence, original input, idempotency key, provider request id,\nand provider operation id when present.\n\nOnly a terminal completed result proves that the connector accepted the\nprovider response and durably settled the action. It does not prove immediate\navailability propagation.\n10. Repeat the same observations\n\nAfter a completed mutation:\n1. read the same event type again;\n2. read the same schedule again after a schedule change;\n3. list calendars again after a selected-calendar change;\n4. repeat busy-time.json if busy evidence remains relevant;\n5. submit the unchanged slot-baseline.json under a new action id.\n\nRepeat the slot query without editing its selector, range, time zone, or format:\n\nexport AFTERSLOTACTIONID='actcalavailabilityslotsafter001'\n\naipctl \\\n  --native-bearer-token-file \"$AIPTOKENFILE\" \\\n  action call \"$AIPURL\" \\\n  cap:caldiy:slot.list \\\n  --action-id \"$AFTERSLOTACTIONID\" \\\n  --mode sync \\\n  --input @slot-baseline.json\n\nCompare the before and after provider payloads and their observation times. A\nchanged result is correlated with the controlled change; it is not a connector\nexplanation of cause. An unchanged result can reflect another availability\nlayer, provider propagation, or provider-owned behavior.\n\nRemove a conflict calendar safely\n\nRemoval is not an exploratory diagnostic step. Use it only when the intended\nstate is to stop considering a known calendar and you have authoritative values\nfor every selector.\n\nWrite conflict-calendar-delete.json. Note that credentialId is a string:\n\n{\n  \"integration\": \"googlecalendar\",\n  \"externalId\": \"team@example.com\",\n  \"credentialId\": \"42\"\n}\n\nSubmit the destructive operation with a new stable identity:\n\nexport CALENDARDELETEACTIONID='actcalavailabilitycalendardelete001'\nexport CALENDARDELETEKEY='cal-availability-calendar-delete-001'\n\naipctl \\\n  --native-bearer-token-file \"$AIPTOKENFILE\" \\\n  action call \"$AIPURL\" \\\n  cap:caldiy:calendar.selected.delete \\\n  --action-id \"$CALENDARDELETEACTIONID\" \\\n  --idempotency-key \"$CALENDARDELETEKEY\" \\\n  --input @conflict-calendar-delete.json\n\nThe client sends every supplied supported field as a DELETE query parameter:\nintegration, externalId, credentialId, and optional\ndelegationCredentialId. Removal is high risk, approval-required,\nretry-unsafe, and has no rollback contract. Adding a calendar later is a new\nmutation, not restoration of the deleted provider state.\n\nDiagnose a missing slot\n\nUse this table after preserving the baseline:\n\n| Check | Evidence to compare | Safe next action |\n\n| Event-type linkage | Actual scheduleId in provider output | Read that exact schedule |\n| Weekly availability | Day and local start/end for the frozen range | Correct one reviewed interval if wrong |\n| Dated override | Override date and local interval | Correct one override if wrong |\n| Booking limits | Window, notice, duration, offset, and buffers | Review event-type configuration |\n| Conflict selection | Exact integration, external id, and credential id | Add only the intended calendar |\n| Busy time | Exact calendar set, range, time zone, and intervals | Inspect the overlapping provider event |\n| Slot query | One selector branch, range, time zone, duration, and format | Correct the query and create a new baseline |\n| Booking plan | Exact requested start and documented planner limits | Use it only for the final booking intent |\n| Provider state | Credential health, response status, request id, and time | Escalate with retained evidence |\n\nThe connector publishes no selected-calendar-specific read and no\navailability-explanation capability. If the remaining question requires either\none, report that evidence gap instead of inventing a reason from nearby data.\n\nRecover without replaying a mutation\n\n| State or failure | Safe response |\n\n| requireshuman | Complete trusted approval for the same action or let it expire |\n| inflight | Read durable status and wait; keep the same action and key |\n| outcomeunknown | Reconcile the original provider operation; do not send a new key |\n| Transport failure after possible dispatch | Treat the mutation as uncertain and reconcile |\n| Authentication failure | Verify tenant, external-account binding, and credential revision |\n| Provider conflict | Refresh the exact schedule or calendar evidence before reviewing a new intent |\n| Rate limit or temporary provider failure on a read | Retry the read within deadline and policy |\n| Invalid action | Correct the input and use a new action for the corrected intent |\n| Idempotency collision | Stop; one key already owns different canonical input |\n\nConnector retries are supported for the reads in this guide, but not for its\nmutations. Never use a new action id or idempotency key merely to escape an\nuncertain mutation state.\n\nEvidence checklist\n\nRetain:\n• catalog revision and capability schema and contract digests;\n• tenant and external-account route, without copying provider credentials;\n• frozen event-type, schedule, range, time zone, calendar, and slot coordinates;\n• before and after event-type, schedule, calendar, busy-time, and slot results;\n• action ids, one mutation idempotency key, approval evidence, and receipts;\n• provider request and operation identifiers when present;\n• observation times and any reported propagation or response-shape gap.\n\nThis evidence supports a bounded comparison. It does not prove live connector\nqualification, provider causality, future bookability, or successful booking.\n\nRelated documentation\n• Slots and reservations (../capabilities/slots-and-reservations.md)\n• Calendars and free/busy (../capabilities/calendars-and-free-busy.md)\n• Schedules (../capabilities/schedules.md)\n• Event types and private links (../capabilities/event-types-and-private-links.md)\n• Error reference (../../../reference/errors.md)\n"
  },
  "integrity": {
    "algorithm": "sha256",
    "sourceDigest": "455ef2bf49a9f071c898fb5c855f5037c9689784b23ea058cdc3572723284157"
  }
}
