{
  "openapi": "3.1.0",
  "info": {
    "title": "CalMonkey API",
    "version": "1",
    "summary": "One calendar API for Google, Microsoft and Apple iCloud.",
    "description": "Read and write your users' Google Calendar, Microsoft 365, Outlook.com and Apple iCloud calendars through one API: hosted connect pages, calendars, free/busy, events with guests, repeating events and meeting links, and signed webhooks.\n\nField names and shapes follow Cronofy's calendar API for the endpoints both have.\n\nDocumentation: https://calmonkey.com/docs (as Markdown: https://calmonkey.com/llms.txt).",
    "contact": {
      "name": "CalMonkey support",
      "email": "support@calmonkey.com",
      "url": "https://calmonkey.com/contact"
    },
    "termsOfService": "https://calmonkey.com/terms"
  },
  "externalDocs": {
    "description": "Documentation",
    "url": "https://calmonkey.com/docs"
  },
  "servers": [
    {
      "url": "https://api.calmonkey.com",
      "description": "The API host: your server calls it."
    }
  ],
  "tags": [
    {
      "name": "OAuth",
      "description": "Connecting a user's calendar and the tokens that follow."
    },
    {
      "name": "Application calendars",
      "description": "Calendars CalMonkey hosts itself, for tests, demos and people with no calendar to connect."
    },
    {
      "name": "Accounts",
      "description": "The account behind a token and the calendar accounts connected to it."
    },
    {
      "name": "Calendars"
    },
    {
      "name": "Free/busy"
    },
    {
      "name": "Events"
    },
    {
      "name": "Channels",
      "description": "Webhook subscriptions."
    }
  ],
  "paths": {
    "/oauth/authorize": {
      "get": {
        "operationId": "authorize",
        "tags": [
          "OAuth"
        ],
        "summary": "Open the hosted connect page",
        "description": "Opened in the user's browser, not called by your server. The user picks a calendar provider, signs in with it and comes back to redirect_uri with ?code=…&state=…, or with ?error=access_denied when they cancel or decline. An unknown client id or a redirect URI that is not registered shows an error page and never redirects.",
        "externalDocs": {
          "url": "https://calmonkey.com/docs/api#authorize"
        },
        "servers": [
          {
            "url": "https://app.calmonkey.com",
            "description": "The app host: what people see in a browser."
          }
        ],
        "security": [],
        "parameters": [
          {
            "name": "response_type",
            "in": "query",
            "required": false,
            "description": "Always code.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "client_id",
            "in": "query",
            "required": false,
            "description": "Your application's client id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "redirect_uri",
            "in": "query",
            "required": false,
            "description": "One of the application's redirect URIs, exactly as registered.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "description": "Defaults to read_write.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "description": "Any value; it comes back unchanged.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "provider_name",
            "in": "query",
            "required": false,
            "description": "Skip the chooser: google, office365, live_connect or apple.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "link_token",
            "in": "query",
            "required": false,
            "description": "From POST /v1/link_tokens: the calendar account connected in this run joins that account.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The hosted connect page.",
            "headers": {
              "Calmonkey-Request-Id": {
                "$ref": "#/components/headers/Calmonkey-Request-Id"
              }
            },
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "302": {
            "description": "On to the calendar provider, or back to redirect_uri with code or error.",
            "headers": {
              "Calmonkey-Request-Id": {
                "$ref": "#/components/headers/Calmonkey-Request-Id"
              }
            }
          },
          "400": {
            "description": "An error page: the client id is unknown or the redirect URI is not registered for it.",
            "headers": {
              "Calmonkey-Request-Id": {
                "$ref": "#/components/headers/Calmonkey-Request-Id"
              }
            },
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/oauth/token": {
      "post": {
        "operationId": "token",
        "tags": [
          "OAuth"
        ],
        "summary": "Exchange a code for tokens, or refresh an access token",
        "description": "grant_type authorization_code needs client_id, client_secret, code and redirect_uri. grant_type refresh_token needs client_id, client_secret and refresh_token; its response has no sub, account_id or linking_profile. Access tokens last 3 hours; the refresh token does not change.",
        "externalDocs": {
          "url": "https://calmonkey.com/docs/api#token"
        },
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TokenRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/TokenRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tokens.",
            "headers": {
              "Calmonkey-Request-Id": {
                "$ref": "#/components/headers/Calmonkey-Request-Id"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                }
              }
            }
          },
          "400": {
            "description": "invalid_client (wrong client id or secret), invalid_grant (code used, expired or for another redirect URI; refresh token revoked), invalid_request (a field is missing) or unsupported_grant_type.",
            "headers": {
              "Calmonkey-Request-Id": {
                "$ref": "#/components/headers/Calmonkey-Request-Id"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/oauth/token/revoke": {
      "post": {
        "operationId": "revokeToken",
        "tags": [
          "OAuth"
        ],
        "summary": "Revoke an account's grant",
        "description": "Needs client_id, client_secret and token (an access or a refresh token). Revokes the whole grant: every token of the account stops working, its channels close, and its stored provider credentials and cached events are deleted. An application calendar is deleted with it.",
        "externalDocs": {
          "url": "https://calmonkey.com/docs/api#revoke"
        },
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RevokeRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/RevokeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Empty body, whether or not the token was known.",
            "headers": {
              "Calmonkey-Request-Id": {
                "$ref": "#/components/headers/Calmonkey-Request-Id"
              }
            }
          },
          "400": {
            "description": "invalid_client or invalid_request.",
            "headers": {
              "Calmonkey-Request-Id": {
                "$ref": "#/components/headers/Calmonkey-Request-Id"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/application_calendars": {
      "post": {
        "operationId": "openApplicationCalendar",
        "tags": [
          "Application calendars"
        ],
        "summary": "Open an application calendar",
        "description": "A calendar hosted by CalMonkey, opened with your client credentials alone: no user and no browser. Creates the calendar on first use and returns tokens for it; the same application_calendar_id always opens the same calendar. The account has one profile and one writable, primary calendar. Needs client_id, client_secret and application_calendar_id.",
        "externalDocs": {
          "url": "https://calmonkey.com/docs/api#application-calendars"
        },
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApplicationCalendarRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/ApplicationCalendarRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tokens for the calendar's account (sub is apc_…).",
            "headers": {
              "Calmonkey-Request-Id": {
                "$ref": "#/components/headers/Calmonkey-Request-Id"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApplicationCalendarResponse"
                }
              }
            }
          },
          "401": {
            "description": "Wrong client credentials. Empty body.",
            "headers": {
              "Calmonkey-Request-Id": {
                "$ref": "#/components/headers/Calmonkey-Request-Id"
              }
            }
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          }
        }
      }
    },
    "/v1/account": {
      "get": {
        "operationId": "getAccount",
        "tags": [
          "Accounts"
        ],
        "summary": "The account behind the token",
        "description": "For an application calendar of an application in Cronofy compatibility mode the answer is 403 with a plain-text body, as Cronofy's.",
        "externalDocs": {
          "url": "https://calmonkey.com/docs/api#account"
        },
        "security": [
          {
            "accessToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "The account.",
            "headers": {
              "Calmonkey-Request-Id": {
                "$ref": "#/components/headers/Calmonkey-Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "An application calendar, in Cronofy compatibility mode.",
            "headers": {
              "Calmonkey-Request-Id": {
                "$ref": "#/components/headers/Calmonkey-Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/userinfo": {
      "get": {
        "operationId": "getUserinfo",
        "tags": [
          "Accounts"
        ],
        "summary": "Who the token belongs to, with every connected profile and its calendars",
        "description": "The type and data are under calmonkey.type and calmonkey.data (cronofy.type and cronofy.data in Cronofy compatibility mode).",
        "externalDocs": {
          "url": "https://calmonkey.com/docs/api#userinfo"
        },
        "security": [
          {
            "accessToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "The account, its profiles and their calendars.",
            "headers": {
              "Calmonkey-Request-Id": {
                "$ref": "#/components/headers/Calmonkey-Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserinfoResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/profiles": {
      "get": {
        "operationId": "listProfiles",
        "tags": [
          "Accounts"
        ],
        "summary": "The calendar accounts the user connected",
        "description": "profile_connected false means the person has to connect that calendar account again: send them through /oauth/authorize with the same provider_name.",
        "externalDocs": {
          "url": "https://calmonkey.com/docs/api#profiles"
        },
        "security": [
          {
            "accessToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "The profiles, each with its calendars.",
            "headers": {
              "Calmonkey-Request-Id": {
                "$ref": "#/components/headers/Calmonkey-Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProfilesResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/calendars": {
      "get": {
        "operationId": "listCalendars",
        "tags": [
          "Calendars"
        ],
        "summary": "List the account's calendars",
        "description": "The same shape for every provider. Write to calendars whose calendar_readonly is false. Calendars deleted at the provider stay in the list with calendar_deleted true.",
        "externalDocs": {
          "url": "https://calmonkey.com/docs/api#calendars"
        },
        "security": [
          {
            "accessToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "The calendars.",
            "headers": {
              "Calmonkey-Request-Id": {
                "$ref": "#/components/headers/Calmonkey-Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CalendarsResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/free_busy": {
      "get": {
        "operationId": "getFreeBusy",
        "tags": [
          "Free/busy"
        ],
        "summary": "Read free/busy",
        "description": "One period per event (one per occurrence of a repeating event). Events your application wrote are left out unless include_managed=true. Up to 1,000 periods per page: follow pages.next_page, an absolute URL, as it is.",
        "externalDocs": {
          "url": "https://calmonkey.com/docs/api#free-busy"
        },
        "security": [
          {
            "accessToken": []
          }
        ],
        "parameters": [
          {
            "name": "tzid",
            "in": "query",
            "required": true,
            "description": "Time zone the request's dates are read in, e.g. Australia/Sydney.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Start: a day (2026-11-03) in tzid, or a time with an offset. Defaults to 42 days ago.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "End, exclusive. Defaults to 201 days from now.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "calendar_ids[]",
            "in": "query",
            "required": false,
            "description": "Only these calendars (up to 100), sent as calendar_ids[]=a&calendar_ids[]=b. Default: every calendar of the account.",
            "schema": {
              "maxItems": 100,
              "type": "array",
              "items": {
                "type": "string",
                "minLength": 1
              }
            },
            "style": "form",
            "explode": true
          },
          {
            "name": "include_managed",
            "in": "query",
            "required": false,
            "description": "Include the events this application created through the API. Default false.",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1",
                "true",
                "false"
              ]
            }
          },
          {
            "name": "include_ids",
            "in": "query",
            "required": false,
            "description": "Add event_id to the periods of events this application created.",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1",
                "true",
                "false"
              ]
            }
          },
          {
            "name": "localized_times",
            "in": "query",
            "required": false,
            "description": "Times with the offset of tzid instead of UTC.",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1",
                "true",
                "false"
              ]
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Position of a later page. Do not build it: follow pages.next_page as it is.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 600
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The busy, tentative and free periods.",
            "headers": {
              "Calmonkey-Request-Id": {
                "$ref": "#/components/headers/Calmonkey-Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FreeBusyResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/events": {
      "get": {
        "operationId": "listEvents",
        "tags": [
          "Events"
        ],
        "summary": "Read events",
        "description": "Every event in the account's calendars from 42 days back to 201 days ahead, with guests, their replies and meeting links. A repeating event is returned as its occurrences. Events your application wrote are left out unless include_managed=true. Up to 300 events per page: follow pages.next_page.",
        "externalDocs": {
          "url": "https://calmonkey.com/docs/api#events-read"
        },
        "security": [
          {
            "accessToken": []
          }
        ],
        "parameters": [
          {
            "name": "tzid",
            "in": "query",
            "required": true,
            "description": "Time zone the request's dates are read in, e.g. Australia/Sydney.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Start: a day (2026-11-03) in tzid, or a time with an offset. Defaults to 42 days ago.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "End, exclusive. Defaults to 201 days from now.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "calendar_ids[]",
            "in": "query",
            "required": false,
            "description": "Only these calendars (up to 100), sent as calendar_ids[]=a&calendar_ids[]=b. Default: every calendar of the account.",
            "schema": {
              "maxItems": 100,
              "type": "array",
              "items": {
                "type": "string",
                "minLength": 1
              }
            },
            "style": "form",
            "explode": true
          },
          {
            "name": "include_managed",
            "in": "query",
            "required": false,
            "description": "Include the events this application created through the API. Default false.",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1",
                "true",
                "false"
              ]
            }
          },
          {
            "name": "only_managed",
            "in": "query",
            "required": false,
            "description": "Only the events this application created.",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1",
                "true",
                "false"
              ]
            }
          },
          {
            "name": "include_deleted",
            "in": "query",
            "required": false,
            "description": "Include events deleted since they were cached (deleted: true).",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1",
                "true",
                "false"
              ]
            }
          },
          {
            "name": "last_modified",
            "in": "query",
            "required": false,
            "description": "Only events changed at or after this time. Use a change notification's changes_since.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "localized_times",
            "in": "query",
            "required": false,
            "description": "Times with the offset of tzid instead of UTC.",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1",
                "true",
                "false"
              ]
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Position of a later page. Do not build it: follow pages.next_page as it is.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 600
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The events.",
            "headers": {
              "Calmonkey-Request-Id": {
                "$ref": "#/components/headers/Calmonkey-Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventsResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/calendars/{calendar_id}/events": {
      "post": {
        "operationId": "upsertEvent",
        "tags": [
          "Events"
        ],
        "summary": "Create or replace an event",
        "description": "Creates the event with this event_id, or replaces it: sending the same body twice leaves one event. attendees invites guests, recurrence makes the event repeat and conferencing adds the calendar's own meeting link. The event is in GET /v1/events and /v1/free_busy as soon as the 202 is sent; the write to the calendar provider follows. Fields the API does not have are accepted and ignored.",
        "externalDocs": {
          "url": "https://calmonkey.com/docs/api#events-upsert"
        },
        "security": [
          {
            "accessToken": []
          }
        ],
        "parameters": [
          {
            "name": "calendar_id",
            "in": "path",
            "required": true,
            "description": "The calendar (cal_…), from GET /v1/calendars.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventUpsertRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Empty body.",
            "headers": {
              "Calmonkey-Request-Id": {
                "$ref": "#/components/headers/Calmonkey-Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ReadOnly"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "deleteEvent",
        "tags": [
          "Events"
        ],
        "summary": "Delete an event, or one occurrence of a repeating event",
        "description": "The body names the event by the event_id it was written with. Without occurrence_date a repeating event is deleted with all its occurrences. Also 202 when there is no such event.",
        "externalDocs": {
          "url": "https://calmonkey.com/docs/api#events-delete"
        },
        "security": [
          {
            "accessToken": []
          }
        ],
        "parameters": [
          {
            "name": "calendar_id",
            "in": "path",
            "required": true,
            "description": "The calendar (cal_…), from GET /v1/calendars.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventDeleteRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Empty body.",
            "headers": {
              "Calmonkey-Request-Id": {
                "$ref": "#/components/headers/Calmonkey-Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ReadOnly"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/calendars/{calendar_id}/events/occurrences": {
      "post": {
        "operationId": "changeOccurrence",
        "tags": [
          "Events"
        ],
        "summary": "Change one occurrence of a repeating event",
        "description": "Gives one occurrence of a repeating event your application wrote its own time, text or both, without sending the series again. The body is everything that differs for this occurrence: it replaces an earlier change of the same occurrence. At least one of a new start and end, summary, description and location is needed.",
        "externalDocs": {
          "url": "https://calmonkey.com/docs/api#events-occurrences"
        },
        "security": [
          {
            "accessToken": []
          }
        ],
        "parameters": [
          {
            "name": "calendar_id",
            "in": "path",
            "required": true,
            "description": "The calendar (cal_…), from GET /v1/calendars.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventOccurrenceRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Empty body.",
            "headers": {
              "Calmonkey-Request-Id": {
                "$ref": "#/components/headers/Calmonkey-Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ReadOnly"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/channels": {
      "post": {
        "operationId": "createChannel",
        "tags": [
          "Channels"
        ],
        "summary": "Create a webhook channel",
        "description": "CalMonkey POSTs a signed notification to callback_url whenever the account's calendars change; a verification notification is sent at once. signing_secret is returned only here. An account has at most 100 open channels. Changes your application made through the API are never notified back to it.",
        "externalDocs": {
          "url": "https://calmonkey.com/docs/api#channels-create"
        },
        "security": [
          {
            "accessToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChannelCreateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The channel.",
            "headers": {
              "Calmonkey-Request-Id": {
                "$ref": "#/components/headers/Calmonkey-Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChannelResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "get": {
        "operationId": "listChannels",
        "tags": [
          "Channels"
        ],
        "summary": "List the account's open channels",
        "description": "Filters that were not set are left out.",
        "externalDocs": {
          "url": "https://calmonkey.com/docs/api#channels-list"
        },
        "security": [
          {
            "accessToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "The open channels.",
            "headers": {
              "Calmonkey-Request-Id": {
                "$ref": "#/components/headers/Calmonkey-Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChannelsResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/channels/{channel_id}": {
      "delete": {
        "operationId": "closeChannel",
        "tags": [
          "Channels"
        ],
        "summary": "Close a channel",
        "description": "Also 202 when the channel was already closed.",
        "externalDocs": {
          "url": "https://calmonkey.com/docs/api#channels-close"
        },
        "security": [
          {
            "accessToken": []
          }
        ],
        "parameters": [
          {
            "name": "channel_id",
            "in": "path",
            "required": true,
            "description": "The channel (chn_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Closed. Empty body.",
            "headers": {
              "Calmonkey-Request-Id": {
                "$ref": "#/components/headers/Calmonkey-Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "An id the account never had.",
            "headers": {
              "Calmonkey-Request-Id": {
                "$ref": "#/components/headers/Calmonkey-Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFound"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/link_tokens": {
      "post": {
        "operationId": "createLinkToken",
        "tags": [
          "Accounts"
        ],
        "summary": "Get a link token, to add another calendar account to this account",
        "description": "Pass it to /oauth/authorize as link_token: the calendar account connected in that run joins the account this access token belongs to. Single use, valid for 5 minutes.",
        "externalDocs": {
          "url": "https://calmonkey.com/docs/api#link-tokens"
        },
        "security": [
          {
            "accessToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "The link token.",
            "headers": {
              "Calmonkey-Request-Id": {
                "$ref": "#/components/headers/Calmonkey-Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LinkTokenResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    }
  },
  "webhooks": {
    "notification": {
      "post": {
        "operationId": "receiveNotification",
        "tags": [
          "Channels"
        ],
        "summary": "What CalMonkey POSTs to a channel's callback URL",
        "description": "Answer with any 2xx within 5 seconds. Anything else, a redirect included, is retried for about 23 hours; 410 closes the channel. Verify the signature over the raw body before trusting it.",
        "externalDocs": {
          "url": "https://calmonkey.com/docs/quickstart#verify"
        },
        "security": [],
        "parameters": [
          {
            "name": "Calmonkey-HMAC-SHA256",
            "in": "header",
            "required": true,
            "description": "Base64 HMAC-SHA256 of the raw body, keyed with your client secret. During a secret rotation, one value per active secret, comma-separated.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Calmonkey-Signature",
            "in": "header",
            "required": false,
            "description": "t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\"> keyed with the channel's whsec_ secret. Not sent to applications in Cronofy compatibility mode.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Calmonkey-Delivery-Id",
            "in": "header",
            "required": true,
            "description": "whd_…: the same on every retry of one notification.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Calmonkey-Delivery-Attempt",
            "in": "header",
            "required": true,
            "description": "1 for the first attempt.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Notification"
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Close the channel: no more notifications are sent to it."
          },
          "2XX": {
            "description": "Delivered."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "accessToken": {
        "type": "http",
        "scheme": "bearer",
        "description": "An account's access token (cmat_…), from POST /oauth/token or POST /v1/application_calendars. Valid for 3 hours; get a new one with the refresh token. The OAuth endpoints and POST /v1/application_calendars take your client id and client secret in the request body instead."
      }
    },
    "headers": {
      "Calmonkey-Request-Id": {
        "description": "Identifies the request. Send your own in the request's Calmonkey-Request-Id header and it comes back unchanged.",
        "schema": {
          "type": "string"
        }
      },
      "RateLimit-Limit": {
        "description": "The burst size of the tighter of the two rate-limit buckets (per application, per access token).",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimit-Remaining": {
        "description": "Requests left in that bucket.",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimit-Reset": {
        "description": "Seconds until that bucket is full again.",
        "schema": {
          "type": "integer"
        }
      },
      "Retry-After": {
        "description": "Seconds to wait before retrying.",
        "schema": {
          "type": "integer"
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "The access token is missing, expired or revoked. Empty body. Refresh the token and retry once.",
        "headers": {
          "Calmonkey-Request-Id": {
            "$ref": "#/components/headers/Calmonkey-Request-Id"
          },
          "WWW-Authenticate": {
            "description": "Bearer realm=\"calmonkey\", error=\"invalid_token\" (or \"invalid_request\" when no token was sent), error_description=\"…\"",
            "schema": {
              "type": "string"
            }
          }
        }
      },
      "ReadOnly": {
        "description": "The calendar is read-only. Empty body.",
        "headers": {
          "Calmonkey-Request-Id": {
            "$ref": "#/components/headers/Calmonkey-Request-Id"
          }
        }
      },
      "NotFound": {
        "description": "A calendar the account does not have (or, on the occurrences endpoint, an event_id your application has not written to it). Empty body.",
        "headers": {
          "Calmonkey-Request-Id": {
            "$ref": "#/components/headers/Calmonkey-Request-Id"
          }
        }
      },
      "ValidationError": {
        "description": "The request is invalid, or asks for something the calendar cannot do. Nothing was written.",
        "headers": {
          "Calmonkey-Request-Id": {
            "$ref": "#/components/headers/Calmonkey-Request-Id"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ValidationError"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Over a rate limit. Empty body. Wait Retry-After seconds, then retry.",
        "headers": {
          "Calmonkey-Request-Id": {
            "$ref": "#/components/headers/Calmonkey-Request-Id"
          },
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimit-Limit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimit-Remaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimit-Reset"
          },
          "Retry-After": {
            "$ref": "#/components/headers/Retry-After"
          }
        }
      }
    },
    "schemas": {
      "TokenRequest": {
        "type": "object",
        "properties": {
          "client_id": {
            "type": "string",
            "maxLength": 500,
            "description": "Your client id. Always needed."
          },
          "client_secret": {
            "type": "string",
            "maxLength": 500,
            "description": "Your client secret. Always needed."
          },
          "grant_type": {
            "type": "string",
            "maxLength": 100,
            "description": "authorization_code or refresh_token. Always needed."
          },
          "code": {
            "type": "string",
            "maxLength": 500,
            "description": "With grant_type authorization_code: the code from the callback. Valid once, for 10 minutes."
          },
          "redirect_uri": {
            "type": "string",
            "maxLength": 2000,
            "description": "With grant_type authorization_code: the redirect URI the authorization request used."
          },
          "refresh_token": {
            "type": "string",
            "maxLength": 500,
            "description": "With grant_type refresh_token: the account's refresh token."
          }
        },
        "additionalProperties": {}
      },
      "TokenResponse": {
        "type": "object",
        "properties": {
          "token_type": {
            "type": "string",
            "const": "bearer"
          },
          "access_token": {
            "type": "string",
            "description": "For the Authorization: Bearer header."
          },
          "expires_in": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "maximum": 9007199254740991,
            "description": "Seconds the access token is valid for: 10800 (3 hours)."
          },
          "refresh_token": {
            "type": "string",
            "description": "Gets new access tokens. Does not change."
          },
          "scope": {
            "type": "string"
          },
          "sub": {
            "type": "string",
            "description": "The account: acc_… (apc_… for an application calendar). Not in a refresh response."
          },
          "account_id": {
            "type": "string",
            "description": "The same value as sub."
          },
          "linking_profile": {
            "type": "object",
            "properties": {
              "provider_name": {
                "type": "string",
                "enum": [
                  "google",
                  "office365",
                  "live_connect",
                  "apple",
                  "calmonkey",
                  "cronofy"
                ]
              },
              "profile_id": {
                "type": "string"
              },
              "profile_name": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "provider_name",
              "profile_id",
              "profile_name"
            ],
            "description": "The calendar account connected in this run."
          }
        },
        "required": [
          "token_type",
          "access_token",
          "expires_in",
          "refresh_token",
          "scope"
        ]
      },
      "RevokeRequest": {
        "type": "object",
        "properties": {
          "client_id": {
            "type": "string",
            "maxLength": 500,
            "description": "Your client id."
          },
          "client_secret": {
            "type": "string",
            "maxLength": 500,
            "description": "Your client secret."
          },
          "token": {
            "type": "string",
            "maxLength": 500,
            "description": "An access token or a refresh token of the account."
          }
        },
        "additionalProperties": {}
      },
      "OAuthError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "invalid_request",
              "invalid_client",
              "invalid_grant",
              "unauthorized_client",
              "unsupported_grant_type",
              "invalid_scope",
              "access_denied",
              "server_error"
            ]
          },
          "error_description": {
            "type": "string"
          }
        },
        "required": [
          "error"
        ]
      },
      "ApplicationCalendarRequest": {
        "type": "object",
        "properties": {
          "client_id": {
            "type": "string",
            "maxLength": 500,
            "description": "Your client id."
          },
          "client_secret": {
            "type": "string",
            "maxLength": 500,
            "description": "Your client secret."
          },
          "application_calendar_id": {
            "description": "Your name for the calendar: a string of up to 255 characters. The same id always opens the same calendar."
          }
        },
        "additionalProperties": {}
      },
      "ApplicationCalendarResponse": {
        "type": "object",
        "properties": {
          "token_type": {
            "type": "string",
            "const": "bearer"
          },
          "access_token": {
            "type": "string",
            "description": "For the Authorization: Bearer header."
          },
          "expires_in": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "maximum": 9007199254740991,
            "description": "Seconds the access token is valid for: 10800 (3 hours)."
          },
          "refresh_token": {
            "type": "string",
            "description": "Gets new access tokens. Does not change."
          },
          "scope": {
            "type": "string"
          },
          "sub": {
            "type": "string",
            "pattern": "^apc_[0-9a-f]{24}$"
          },
          "account_id": {
            "type": "string",
            "description": "The same value as sub."
          },
          "linking_profile": {
            "type": "object",
            "properties": {
              "provider_name": {
                "type": "string",
                "enum": [
                  "google",
                  "office365",
                  "live_connect",
                  "apple",
                  "calmonkey",
                  "cronofy"
                ]
              },
              "profile_id": {
                "type": "string"
              },
              "profile_name": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "provider_name",
              "profile_id",
              "profile_name"
            ],
            "description": "The calendar account connected in this run."
          },
          "application_calendar_id": {
            "type": "string"
          }
        },
        "required": [
          "token_type",
          "access_token",
          "expires_in",
          "refresh_token",
          "scope",
          "sub",
          "application_calendar_id"
        ]
      },
      "AccountResponse": {
        "type": "object",
        "properties": {
          "account": {
            "type": "object",
            "properties": {
              "account_id": {
                "type": "string"
              },
              "type": {
                "type": "string",
                "enum": [
                  "account",
                  "application_calendar"
                ]
              },
              "email": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "scope": {
                "type": "string"
              },
              "default_tzid": {
                "type": "string"
              }
            },
            "required": [
              "account_id",
              "type",
              "email",
              "name",
              "scope",
              "default_tzid"
            ]
          }
        },
        "required": [
          "account"
        ]
      },
      "UserinfoResponse": {
        "type": "object",
        "properties": {
          "sub": {
            "type": "string",
            "description": "The account: acc_… (apc_… for an application calendar)."
          },
          "application_calendar_id": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "zoneinfo": {
            "type": "string"
          },
          "calmonkey.type": {
            "type": "string",
            "enum": [
              "account",
              "application_calendar"
            ]
          },
          "calmonkey.data": {
            "type": "object",
            "properties": {
              "authorization": {
                "type": "object",
                "properties": {
                  "scope": {
                    "type": "string"
                  },
                  "status": {
                    "type": "string",
                    "const": "active"
                  }
                },
                "required": [
                  "scope",
                  "status"
                ]
              },
              "application_calendar": {
                "type": "object",
                "properties": {
                  "application_calendar_id": {
                    "type": "string"
                  }
                },
                "required": [
                  "application_calendar_id"
                ]
              },
              "profiles": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "provider_name": {
                      "type": "string",
                      "enum": [
                        "google",
                        "office365",
                        "live_connect",
                        "apple",
                        "calmonkey",
                        "cronofy"
                      ]
                    },
                    "provider_service": {
                      "type": "string",
                      "enum": [
                        "gmail",
                        "gsuite",
                        "office365",
                        "outlook_com",
                        "icloud",
                        "cronofy",
                        "calmonkey"
                      ]
                    },
                    "profile_id": {
                      "type": "string"
                    },
                    "profile_name": {
                      "type": "string"
                    },
                    "profile_connected": {
                      "type": "boolean"
                    },
                    "profile_initial_sync_required": {
                      "type": "boolean"
                    },
                    "profile_calendars": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "calendar_id": {
                            "type": "string"
                          },
                          "calendar_name": {
                            "type": "string"
                          },
                          "calendar_readonly": {
                            "type": "boolean"
                          },
                          "calendar_deleted": {
                            "type": "boolean"
                          },
                          "calendar_primary": {
                            "type": "boolean"
                          },
                          "calendar_integrated_conferencing_available": {
                            "type": "boolean"
                          },
                          "calendar_attachments_available": {
                            "type": "boolean"
                          },
                          "permission_level": {
                            "type": "string",
                            "enum": [
                              "sandbox",
                              "unrestricted"
                            ]
                          }
                        },
                        "required": [
                          "calendar_id",
                          "calendar_name",
                          "calendar_readonly",
                          "calendar_deleted",
                          "calendar_primary",
                          "calendar_integrated_conferencing_available",
                          "calendar_attachments_available",
                          "permission_level"
                        ]
                      }
                    }
                  },
                  "required": [
                    "provider_name",
                    "provider_service",
                    "profile_id",
                    "profile_name",
                    "profile_connected",
                    "profile_initial_sync_required",
                    "profile_calendars"
                  ]
                }
              }
            },
            "required": [
              "authorization",
              "profiles"
            ]
          },
          "cronofy.type": {
            "type": "string",
            "enum": [
              "account",
              "application_calendar"
            ],
            "description": "In place of calmonkey.type for applications in Cronofy compatibility mode."
          },
          "cronofy.data": {
            "type": "object",
            "properties": {
              "authorization": {
                "type": "object",
                "properties": {
                  "scope": {
                    "type": "string"
                  },
                  "status": {
                    "type": "string",
                    "const": "active"
                  }
                },
                "required": [
                  "scope",
                  "status"
                ]
              },
              "application_calendar": {
                "type": "object",
                "properties": {
                  "application_calendar_id": {
                    "type": "string"
                  }
                },
                "required": [
                  "application_calendar_id"
                ]
              },
              "profiles": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "provider_name": {
                      "type": "string",
                      "enum": [
                        "google",
                        "office365",
                        "live_connect",
                        "apple",
                        "calmonkey",
                        "cronofy"
                      ]
                    },
                    "provider_service": {
                      "type": "string",
                      "enum": [
                        "gmail",
                        "gsuite",
                        "office365",
                        "outlook_com",
                        "icloud",
                        "cronofy",
                        "calmonkey"
                      ]
                    },
                    "profile_id": {
                      "type": "string"
                    },
                    "profile_name": {
                      "type": "string"
                    },
                    "profile_connected": {
                      "type": "boolean"
                    },
                    "profile_initial_sync_required": {
                      "type": "boolean"
                    },
                    "profile_calendars": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "calendar_id": {
                            "type": "string"
                          },
                          "calendar_name": {
                            "type": "string"
                          },
                          "calendar_readonly": {
                            "type": "boolean"
                          },
                          "calendar_deleted": {
                            "type": "boolean"
                          },
                          "calendar_primary": {
                            "type": "boolean"
                          },
                          "calendar_integrated_conferencing_available": {
                            "type": "boolean"
                          },
                          "calendar_attachments_available": {
                            "type": "boolean"
                          },
                          "permission_level": {
                            "type": "string",
                            "enum": [
                              "sandbox",
                              "unrestricted"
                            ]
                          }
                        },
                        "required": [
                          "calendar_id",
                          "calendar_name",
                          "calendar_readonly",
                          "calendar_deleted",
                          "calendar_primary",
                          "calendar_integrated_conferencing_available",
                          "calendar_attachments_available",
                          "permission_level"
                        ]
                      }
                    }
                  },
                  "required": [
                    "provider_name",
                    "provider_service",
                    "profile_id",
                    "profile_name",
                    "profile_connected",
                    "profile_initial_sync_required",
                    "profile_calendars"
                  ]
                }
              }
            },
            "required": [
              "authorization",
              "profiles"
            ],
            "description": "In place of calmonkey.data for applications in Cronofy compatibility mode."
          }
        },
        "required": [
          "sub"
        ]
      },
      "ProfilesResponse": {
        "type": "object",
        "properties": {
          "profiles": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "provider_name": {
                  "type": "string",
                  "enum": [
                    "google",
                    "office365",
                    "live_connect",
                    "apple",
                    "calmonkey",
                    "cronofy"
                  ]
                },
                "provider_service": {
                  "type": "string",
                  "enum": [
                    "gmail",
                    "gsuite",
                    "office365",
                    "outlook_com",
                    "icloud",
                    "cronofy",
                    "calmonkey"
                  ]
                },
                "profile_id": {
                  "type": "string"
                },
                "profile_name": {
                  "type": "string"
                },
                "profile_connected": {
                  "type": "boolean"
                },
                "profile_relink_url": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "profile_initial_sync_required": {
                  "type": "boolean"
                },
                "profile_calendars": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "calendar_id": {
                        "type": "string"
                      },
                      "calendar_name": {
                        "type": "string"
                      },
                      "calendar_readonly": {
                        "type": "boolean"
                      },
                      "calendar_deleted": {
                        "type": "boolean"
                      },
                      "calendar_primary": {
                        "type": "boolean"
                      },
                      "calendar_integrated_conferencing_available": {
                        "type": "boolean"
                      },
                      "calendar_attachments_available": {
                        "type": "boolean"
                      },
                      "permission_level": {
                        "type": "string",
                        "enum": [
                          "sandbox",
                          "unrestricted"
                        ]
                      }
                    },
                    "required": [
                      "calendar_id",
                      "calendar_name",
                      "calendar_readonly",
                      "calendar_deleted",
                      "calendar_primary",
                      "calendar_integrated_conferencing_available",
                      "calendar_attachments_available",
                      "permission_level"
                    ]
                  }
                }
              },
              "required": [
                "provider_name",
                "provider_service",
                "profile_id",
                "profile_name",
                "profile_connected",
                "profile_relink_url",
                "profile_initial_sync_required",
                "profile_calendars"
              ]
            }
          }
        },
        "required": [
          "profiles"
        ]
      },
      "CalendarsResponse": {
        "type": "object",
        "properties": {
          "calendars": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "provider_name": {
                  "type": "string",
                  "enum": [
                    "google",
                    "office365",
                    "live_connect",
                    "apple",
                    "calmonkey",
                    "cronofy"
                  ]
                },
                "profile_id": {
                  "type": "string"
                },
                "profile_name": {
                  "type": "string"
                },
                "calendar_id": {
                  "type": "string"
                },
                "calendar_name": {
                  "type": "string"
                },
                "calendar_readonly": {
                  "type": "boolean"
                },
                "calendar_deleted": {
                  "type": "boolean"
                },
                "calendar_primary": {
                  "type": "boolean"
                },
                "calendar_integrated_conferencing_available": {
                  "type": "boolean"
                },
                "calendar_attachments_available": {
                  "type": "boolean"
                },
                "permission_level": {
                  "type": "string",
                  "enum": [
                    "sandbox",
                    "unrestricted"
                  ]
                }
              },
              "required": [
                "provider_name",
                "profile_id",
                "profile_name",
                "calendar_id",
                "calendar_name",
                "calendar_readonly",
                "calendar_deleted",
                "calendar_primary",
                "calendar_integrated_conferencing_available",
                "calendar_attachments_available",
                "permission_level"
              ]
            }
          },
          "sub": {
            "type": "string"
          }
        },
        "required": [
          "calendars"
        ]
      },
      "FreeBusyResponse": {
        "type": "object",
        "properties": {
          "pages": {
            "type": "object",
            "properties": {
              "current": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "total": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "next_page": {
                "type": "string",
                "description": "Absolute URL of the next page. Absent on the last page."
              }
            },
            "required": [
              "current",
              "total"
            ]
          },
          "free_busy": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "calendar_id": {
                  "type": "string"
                },
                "event_uid": {
                  "type": "string",
                  "description": "Identifies the event (evt_…). Applications in Cronofy compatibility mode get it only with include_ids=true."
                },
                "start": {
                  "type": "string",
                  "description": "A time, or a date for an all-day event."
                },
                "end": {
                  "type": "string",
                  "description": "A time, or a date (exclusive) for an all-day event."
                },
                "free_busy_status": {
                  "type": "string",
                  "enum": [
                    "busy",
                    "tentative",
                    "free",
                    "unknown"
                  ]
                },
                "event_id": {
                  "type": "string",
                  "description": "Only with include_ids=true, and only on events the calling application created: the id it chose."
                }
              },
              "required": [
                "calendar_id",
                "start",
                "end",
                "free_busy_status"
              ]
            }
          }
        },
        "required": [
          "pages",
          "free_busy"
        ]
      },
      "EventsResponse": {
        "type": "object",
        "properties": {
          "pages": {
            "type": "object",
            "properties": {
              "current": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "total": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "next_page": {
                "type": "string",
                "description": "Absolute URL of the next page. Absent on the last page."
              }
            },
            "required": [
              "current",
              "total"
            ]
          },
          "events": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "calendar_id": {
                  "type": "string"
                },
                "event_uid": {
                  "type": "string"
                },
                "event_id": {
                  "type": "string",
                  "description": "Only on events the calling application created: the id it chose."
                },
                "summary": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                },
                "start": {
                  "type": "string",
                  "description": "A time, or a date for an all-day event."
                },
                "end": {
                  "type": "string",
                  "description": "A time, or a date (exclusive) for an all-day event."
                },
                "deleted": {
                  "type": "boolean"
                },
                "created": {
                  "type": "string"
                },
                "updated": {
                  "type": "string"
                },
                "location": {
                  "type": "object",
                  "properties": {
                    "description": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "description"
                  ]
                },
                "url": {
                  "type": "string"
                },
                "participation_status": {
                  "type": "string",
                  "enum": [
                    "needs_action",
                    "accepted",
                    "tentative",
                    "declined",
                    "unknown"
                  ],
                  "description": "The calendar owner's own reply."
                },
                "attendees": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "email": {
                        "type": "string"
                      },
                      "display_name": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "status": {
                        "type": "string",
                        "enum": [
                          "needs_action",
                          "accepted",
                          "tentative",
                          "declined",
                          "unknown"
                        ]
                      }
                    },
                    "required": [
                      "email",
                      "display_name",
                      "status"
                    ]
                  }
                },
                "transparency": {
                  "type": "string",
                  "enum": [
                    "opaque",
                    "transparent"
                  ]
                },
                "extended_transparency": {
                  "type": "string",
                  "enum": [
                    "opaque",
                    "transparent"
                  ]
                },
                "event_private": {
                  "type": "boolean"
                },
                "organizer": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "email": {
                          "type": "string"
                        },
                        "display_name": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "email",
                        "display_name"
                      ]
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "conferencing": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "pending": {
                          "type": "boolean",
                          "const": true
                        }
                      },
                      "required": [
                        "pending"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "provider_name": {
                          "type": "string"
                        },
                        "join_url": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "provider_name",
                        "join_url"
                      ]
                    }
                  ]
                },
                "series_identifier": {
                  "type": "string",
                  "description": "On every occurrence of a repeating event: the same value for all occurrences of one series."
                },
                "series_master": {
                  "type": "object",
                  "properties": {
                    "event_id": {
                      "type": "string"
                    },
                    "event_uid": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "event_id",
                    "event_uid"
                  ]
                },
                "occurrence_date": {
                  "type": "string",
                  "description": "On an occurrence of a repeating event: its original day in the series' time zone (YYYY-MM-DD)."
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "confirmed",
                    "tentative",
                    "cancelled"
                  ]
                },
                "categories": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "recurring": {
                  "type": "boolean"
                },
                "recurrence": {
                  "type": "object",
                  "properties": {
                    "rules": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "frequency": {
                            "type": "string"
                          },
                          "interval": {
                            "type": "number"
                          },
                          "count": {
                            "type": "number"
                          },
                          "until": {
                            "type": "string"
                          },
                          "by_day": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "day": {
                                  "type": "string"
                                },
                                "nth_of_period": {
                                  "type": "number"
                                }
                              },
                              "required": [
                                "day"
                              ]
                            }
                          }
                        },
                        "required": [
                          "frequency"
                        ]
                      }
                    }
                  },
                  "required": [
                    "rules"
                  ]
                },
                "options": {
                  "type": "object",
                  "properties": {
                    "delete": {
                      "type": "boolean"
                    },
                    "update": {
                      "type": "boolean"
                    },
                    "change_participation_status": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "delete",
                    "update",
                    "change_participation_status"
                  ]
                }
              },
              "required": [
                "calendar_id",
                "event_uid",
                "summary",
                "description",
                "start",
                "end",
                "deleted",
                "created",
                "updated",
                "participation_status",
                "attendees",
                "transparency",
                "extended_transparency",
                "event_private",
                "organizer",
                "status",
                "categories",
                "recurring",
                "options"
              ]
            }
          }
        },
        "required": [
          "pages",
          "events"
        ]
      },
      "EventUpsertRequest": {
        "type": "object",
        "properties": {
          "event_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Your id for the event. Unique per calendar and application: writing it again replaces the event."
          },
          "summary": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2000,
            "description": "Title."
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 50000
              },
              {
                "type": "null"
              }
            ]
          },
          "start": {
            "description": "A time with an offset (2026-11-03T03:00:00Z), a date for an all-day event, or { \"time\": \"…\", \"tzid\": \"…\" }.",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "object",
                "properties": {
                  "time": {
                    "type": "string"
                  },
                  "tzid": {
                    "type": "string"
                  }
                },
                "required": [
                  "time"
                ]
              }
            ]
          },
          "end": {
            "description": "As start: a date when start is a date (exclusive), a time when start is a time, not before start.",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "object",
                "properties": {
                  "time": {
                    "type": "string"
                  },
                  "tzid": {
                    "type": "string"
                  }
                },
                "required": [
                  "time"
                ]
              }
            ]
          },
          "tzid": {
            "type": "string",
            "description": "The event's time zone, e.g. Australia/Sydney. Needed for a repeating event with a time."
          },
          "location": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "description": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 2000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2048,
                "description": "A link, returned on reads."
              },
              {
                "type": "null"
              }
            ]
          },
          "transparency": {
            "type": "string",
            "enum": [
              "opaque",
              "transparent"
            ],
            "description": "opaque (busy, the default) or transparent (shown as free)."
          },
          "attendees": {
            "type": "object",
            "properties": {
              "invite": {
                "maxItems": 100,
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "email": {
                      "type": "string",
                      "maxLength": 254
                    },
                    "display_name": {
                      "anyOf": [
                        {
                          "type": "string",
                          "maxLength": 256
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "email"
                  ]
                }
              },
              "remove": {
                "maxItems": 100,
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "email": {
                      "type": "string",
                      "maxLength": 254
                    },
                    "display_name": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "email"
                  ]
                }
              }
            },
            "description": "A change to the event's guests, not the whole list: the guests after the write are the guests it had, plus invite, minus remove."
          },
          "notify_attendees": {
            "type": "boolean",
            "description": "Whether the calendar tells the guests about this write. Default true."
          },
          "recurrence": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "rules": {
                    "minItems": 1,
                    "maxItems": 1,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "frequency": {
                          "type": "string",
                          "enum": [
                            "daily",
                            "weekly",
                            "monthly",
                            "yearly"
                          ]
                        },
                        "interval": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 99,
                          "description": "Every how many days, weeks, months or years. Default 1."
                        },
                        "count": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 730,
                          "description": "How many occurrences in all, the first included. Not together with until."
                        },
                        "until": {
                          "type": "string",
                          "description": "The last day an occurrence may fall on (YYYY-MM-DD, inclusive, in the event's time zone). Not together with count."
                        },
                        "by_day": {
                          "minItems": 1,
                          "maxItems": 35,
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "day": {
                                "type": "string",
                                "enum": [
                                  "monday",
                                  "tuesday",
                                  "wednesday",
                                  "thursday",
                                  "friday",
                                  "saturday",
                                  "sunday"
                                ]
                              },
                              "nth_of_period": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              }
                            },
                            "required": [
                              "day"
                            ]
                          }
                        }
                      },
                      "required": [
                        "frequency"
                      ]
                    }
                  },
                  "exceptions": {
                    "type": "object",
                    "properties": {
                      "add": {
                        "maxItems": 64,
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "date": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "date"
                          ]
                        },
                        "description": "Days to skip, each an occurrence's original day (YYYY-MM-DD)."
                      },
                      "change": {
                        "maxItems": 64,
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "date": {
                              "type": "string"
                            },
                            "start": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "object",
                                  "properties": {
                                    "time": {
                                      "type": "string"
                                    },
                                    "tzid": {
                                      "type": "string"
                                    }
                                  },
                                  "required": [
                                    "time"
                                  ]
                                }
                              ]
                            },
                            "end": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "object",
                                  "properties": {
                                    "time": {
                                      "type": "string"
                                    },
                                    "tzid": {
                                      "type": "string"
                                    }
                                  },
                                  "required": [
                                    "time"
                                  ]
                                }
                              ]
                            },
                            "summary": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 2000
                            },
                            "description": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "maxLength": 50000
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "location": {
                              "anyOf": [
                                {
                                  "type": "object",
                                  "properties": {
                                    "description": {
                                      "anyOf": [
                                        {
                                          "type": "string",
                                          "maxLength": 2000
                                        },
                                        {
                                          "type": "null"
                                        }
                                      ]
                                    }
                                  }
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "date"
                          ]
                        },
                        "description": "Occurrences with a time or text of their own, each named by its original day."
                      }
                    }
                  }
                },
                "required": [
                  "rules"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "How the event repeats: one rule, and exceptions. null stops it repeating; left out, a series stays as it is."
          },
          "conferencing": {
            "type": "object",
            "properties": {
              "profile_id": {
                "type": "string",
                "description": "default (add the calendar's own link where it has one), integrated (the same, and 422 on a calendar that has none) or none (take the link off)."
              }
            },
            "required": [
              "profile_id"
            ],
            "description": "Asks the calendar to add its own meeting link, or to take it off."
          }
        },
        "required": [
          "event_id",
          "summary",
          "start",
          "end"
        ]
      },
      "EventDeleteRequest": {
        "type": "object",
        "properties": {
          "event_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "The id the event was written with."
          },
          "occurrence_date": {
            "type": "string",
            "description": "Cancel only this occurrence of a repeating event: its original day in the event's time zone (YYYY-MM-DD)."
          },
          "notify_attendees": {
            "type": "boolean",
            "description": "Whether guests are sent the cancellation. Default true."
          }
        },
        "required": [
          "event_id"
        ]
      },
      "EventOccurrenceRequest": {
        "type": "object",
        "properties": {
          "event_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "The id the series was written with."
          },
          "occurrence_date": {
            "type": "string",
            "description": "The occurrence's original day in the event's time zone (YYYY-MM-DD)."
          },
          "tzid": {
            "type": "string",
            "description": "The time zone of the new time. Default: the series' own."
          },
          "start": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "object",
                "properties": {
                  "time": {
                    "type": "string"
                  },
                  "tzid": {
                    "type": "string"
                  }
                },
                "required": [
                  "time"
                ]
              }
            ]
          },
          "end": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "object",
                "properties": {
                  "time": {
                    "type": "string"
                  },
                  "tzid": {
                    "type": "string"
                  }
                },
                "required": [
                  "time"
                ]
              }
            ]
          },
          "summary": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2000
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 50000
              },
              {
                "type": "null"
              }
            ]
          },
          "location": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "description": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 2000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "notify_attendees": {
            "type": "boolean",
            "description": "Whether guests are told. Default true."
          }
        },
        "required": [
          "event_id",
          "occurrence_date"
        ]
      },
      "ChannelCreateRequest": {
        "type": "object",
        "properties": {
          "callback_url": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2048,
            "description": "Where notifications are POSTed: https, port 443, a public host, no credentials in the URL."
          },
          "filters": {
            "type": "object",
            "properties": {
              "calendar_ids": {
                "maxItems": 200,
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 200
                },
                "description": "Only changes in these calendars (cal_…). Absent or empty: every calendar of the account."
              },
              "only_managed": {
                "type": "boolean",
                "description": "Only changes to events this application created through the API."
              }
            }
          }
        },
        "required": [
          "callback_url"
        ]
      },
      "ChannelResponse": {
        "type": "object",
        "properties": {
          "channel": {
            "type": "object",
            "properties": {
              "channel_id": {
                "type": "string"
              },
              "callback_url": {
                "type": "string"
              },
              "filters": {
                "type": "object",
                "properties": {
                  "calendar_ids": {
                    "maxItems": 200,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200
                    },
                    "description": "Only changes in these calendars (cal_…). Absent or empty: every calendar of the account."
                  },
                  "only_managed": {
                    "type": "boolean",
                    "description": "Only changes to events this application created through the API."
                  }
                }
              },
              "signing_secret": {
                "type": "string",
                "description": "The whsec_… secret of the Calmonkey-Signature header. Returned once, when the channel is created; not sent to applications in Cronofy compatibility mode."
              }
            },
            "required": [
              "channel_id",
              "callback_url",
              "filters"
            ]
          }
        },
        "required": [
          "channel"
        ]
      },
      "ChannelsResponse": {
        "type": "object",
        "properties": {
          "channels": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "channel_id": {
                  "type": "string"
                },
                "callback_url": {
                  "type": "string"
                },
                "filters": {
                  "type": "object",
                  "properties": {
                    "calendar_ids": {
                      "maxItems": 200,
                      "type": "array",
                      "items": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 200
                      },
                      "description": "Only changes in these calendars (cal_…). Absent or empty: every calendar of the account."
                    },
                    "only_managed": {
                      "type": "boolean",
                      "description": "Only changes to events this application created through the API."
                    }
                  }
                }
              },
              "required": [
                "channel_id",
                "callback_url",
                "filters"
              ]
            }
          }
        },
        "required": [
          "channels"
        ]
      },
      "LinkTokenResponse": {
        "type": "object",
        "properties": {
          "link_token": {
            "type": "string",
            "description": "Pass it to /oauth/authorize as link_token. Single use, valid for 5 minutes."
          }
        },
        "required": [
          "link_token"
        ]
      },
      "Notification": {
        "type": "object",
        "properties": {
          "notification": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "verification",
                  "change",
                  "profile_disconnected",
                  "profile_initial_sync_completed"
                ]
              },
              "changes_since": {
                "type": "string",
                "description": "With type change: read events modified since this time (UTC, whole seconds)."
              }
            },
            "required": [
              "type"
            ]
          },
          "channel": {
            "type": "object",
            "properties": {
              "channel_id": {
                "type": "string"
              },
              "callback_url": {
                "type": "string"
              },
              "filters": {
                "type": "object",
                "properties": {
                  "calendar_ids": {
                    "maxItems": 200,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200
                    },
                    "description": "Only changes in these calendars (cal_…). Absent or empty: every calendar of the account."
                  },
                  "only_managed": {
                    "type": "boolean",
                    "description": "Only changes to events this application created through the API."
                  }
                }
              }
            },
            "required": [
              "channel_id",
              "callback_url",
              "filters"
            ]
          }
        },
        "required": [
          "notification",
          "channel"
        ]
      },
      "ValidationError": {
        "type": "object",
        "properties": {
          "errors": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "key": {
                    "type": "string",
                    "description": "What is wrong, e.g. errors.required. Match on this."
                  },
                  "description": {
                    "type": "string",
                    "description": "The same in words, for people. May be reworded."
                  }
                },
                "required": [
                  "key",
                  "description"
                ]
              }
            }
          }
        },
        "required": [
          "errors"
        ],
        "description": "Every field with a problem, by its path in the request (start, location.description, calendar_ids[0]; base for the whole body), each with a list of { key, description }. Keys: errors.required, errors.invalid, errors.invalid_type, errors.invalid_format, errors.invalid_value, errors.too_small, errors.too_big, errors.invalid_json, errors.invalid_callback_url, errors.invalid_callback_url_blocked, errors.too_many_channels, errors.invalid_email, errors.too_many_attendees, errors.attendees_unsupported, errors.notify_attendees_unsupported, errors.conferencing_unavailable, errors.max_recurrence_rules_exceeded, errors.not_recognized, errors.not_supported, errors.must_be_integer_greater_than_zero, errors.must_be_date, errors.not_supported_count_until_combination, errors.not_recurring, errors.not_an_occurrence. Applications in Cronofy compatibility mode get Cronofy's wording, with these keys in place of ours: errors.tzid_unrecognized, errors.invalid_time_pair, errors.event.cannot_set_attendees, errors.integrated_conferencing_not_available.",
        "x-error-keys": [
          "errors.required",
          "errors.invalid",
          "errors.invalid_type",
          "errors.invalid_format",
          "errors.invalid_value",
          "errors.too_small",
          "errors.too_big",
          "errors.invalid_json",
          "errors.invalid_callback_url",
          "errors.invalid_callback_url_blocked",
          "errors.too_many_channels",
          "errors.invalid_email",
          "errors.too_many_attendees",
          "errors.attendees_unsupported",
          "errors.notify_attendees_unsupported",
          "errors.conferencing_unavailable",
          "errors.max_recurrence_rules_exceeded",
          "errors.not_recognized",
          "errors.not_supported",
          "errors.must_be_integer_greater_than_zero",
          "errors.must_be_date",
          "errors.not_supported_count_until_combination",
          "errors.not_recurring",
          "errors.not_an_occurrence"
        ]
      },
      "NotFound": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "const": "not_found"
          },
          "description": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "description"
        ]
      }
    }
  }
}
