{"package":"@executor.sh/google","files":[{"path":"README.md","content":"# Google\n\nEvery linked Google account across Google's productivity APIs, in two layers:\n\n- **Curated tools** at the top level, shaped for agents after [gogcli](https://github.com/openclaw/gogcli)'s typed tool set. Reads span every linked account at once (the app's requirement is `google.many()`) unless `account` names one by address, and each result says which account it came from. `search` looks through mail, Drive, calendar events and contacts in one call; `gmail.search`/`readThread`/`readMessage`/`labels`/`attachment` return decoded text instead of MIME, and `send`/`draft` take plain fields and handle replies (thread, `Re:` subject, `In-Reply-To`, reply-all); `gmail.modify` archives, marks read, stars, trashes and labels by name; `calendar.agenda` merges every shown calendar of every account and lists shared meetings once, `calendar.freeBusy` merges busy time across accounts and proposes free slots within working hours, and `createEvent`/`respond` take plain fields (with a Meet link on request); `drive.search` takes plain words or Drive query syntax and `drive.read` returns any file as text (Docs as Markdown, Sheets as CSV); `sheets.read`/`append`/`write`; `contacts.search` covers saved contacts, other contacts and the Workspace directory; `tasks.list`/`add`/`complete` cover every list. Their code is `curated.ts` (`accounts` and `search`) and `tools/`, copied from `shared/google-tools` by `node scripts/google-vendor.ts`; the single-product packages carry the same tools for their product.\n- **The complete APIs** under `api`: Gmail (`api.gmail`, 79 tools), Google Calendar (`api.calendar`, 38), Google Drive (`api.drive`, 64), Google Sheets (`api.sheets`, 17), Google Docs (`api.docs`, 17), Google Slides (`api.slides`, 19), Google Forms (`api.forms`, 9), Google Tasks (`api.tasks`, 14), Google Contacts through the People API (`api.contacts`, 24), Google Meet (`api.meet`, 24) and Google Photos (`api.photos.library`, 12; `api.photos.picker`, 4): 321 tools, each taking an `accountId` from the top-level `accounts` tool.\n\nEvery mutation in both layers asks for approval. It is the all-in-one alternative to the single-product packages (`gmail`, `google-calendar`, `google-drive`, `google-sheets`, `google-docs`, `google-slides`, `google-forms`, `google-tasks`, `google-contacts`, `google-meet`, `google-photos`), with one sign-in per account instead of one per product, and matches the scope of Composio's \"Google Super\" toolkit where Executor can sign in to it.\n\n## Interface\n\nThe curated tools call Google's REST APIs directly. Under `api`, nothing is new: `products/` holds copies of the single-product packages' sources, written by `node scripts/google-vendor.ts` (`--check` reports stale copies), because a catalog package must contain all of its own files. Edit the original package and rerun the script. The OpenAPI products use the same documents as their packages: APIs.guru's unofficial conversions of Google's Discovery documents for Gmail, Sheets, Forms and Tasks (fetched live from `https://api.apis.guru/v2/specs/googleapis.com/<api>/<version>/openapi.json`), and checked-in conversions of Google's own Discovery documents for Calendar, Drive, People and Photos (see those packages' READMEs). Docs, Slides and Meet are the hand-written tools of `google-docs`, `google-slides` and `google-meet` (each package's `tools.ts`). Each product keeps its package's known gaps.\n\n## Auth\n\nOAuth 2.0, discovered from `https://accounts.google.com`, with `access_type=offline` and `prompt=consent` so Google returns a refresh token. On Executor Cloud the connect page can use the hosted \"Executor for Google\" client, because every scope requested is on its allowlist. Otherwise create a \"Web application\" OAuth client in Google Cloud (Google Auth Platform > Clients), enable the Gmail, Calendar, Drive, Sheets, Docs, Slides, Forms, Tasks, People, Meet REST, Photos Library and Photos Picker APIs, add the redirect URI shown on the connect page (`/api/oauth/callback` on the Executor origin) and paste the client ID and secret into the connect page. Scopes: `openid`, `email`, `profile`, `https://mail.google.com/`, `gmail.settings.basic`, `calendar`, `drive`, `spreadsheets`, `documents`, `presentations`, `forms.body`, `forms.responses.readonly`, `tasks`, `contacts`, `contacts.other.readonly`, `directory.readonly`, `meetings.space.created`, `meetings.space.readonly`, `meetings.space.settings`, `photoslibrary.appendonly`, `photoslibrary.readonly.appcreateddata`, `photoslibrary.edit.appcreateddata` and `photospicker.mediaitems.readonly`. Gmail's and Drive's are restricted scopes: a self-made client outside its test users needs Google's restricted-scope verification. The health check reads the Gmail profile (`users/me/profile`) for the account's address; the curated tools read it from `oauth2/v3/userinfo`, cached per account for a day.\n\n## Known gaps\n\n- Left out because Executor for Google's scope allowlist does not include their scopes, and requesting them would stop Executor Cloud from offering its hosted client: Google Chat (`chat.*` scopes; use `google-chat`), Google Analytics (`analytics.*`; use `google-analytics`) and Google Ads (`adwords`, plus a developer token; use `google-ads`). Composio's Google Super also bundles Maps and Places, which take an API key rather than a user's OAuth token; use `google-maps`.\n- Search Console, BigQuery, YouTube and Workspace Admin are not part of Google Super and have their own packages.\n- Every gap listed in the single-product packages' READMEs applies here, such as Gmail's permanent-delete and delegation tools, which need scopes not requested.\n- The curated tools leave out what gogcli gates hardest: permanent deletion, and sending with attachments (drafts and sends carry a text or HTML body only). Both remain possible through `api.gmail`.\n"},{"path":"curated.ts","content":"// The curated tools: per-product routers from tools/ (copies of shared/google-tools, written by\n// scripts/google-vendor.ts), plus the two tools that span products.\nimport { number, object, query, router, string, type RouterChild, type RouterOptions } from \"apps\";\nimport { calendar, listEvents } from \"./tools/calendar.js\";\nimport { drive, driveQuery, searchFiles } from \"./tools/drive.js\";\nimport { gmail, searchMail } from \"./tools/gmail.js\";\nimport { contacts, findPeople } from \"./tools/people.js\";\nimport { fanOut, linked, select, type Context, type Source } from \"./tools/shared.js\";\nimport { sheets } from \"./tools/sheets.js\";\nimport { tasks } from \"./tools/tasks.js\";\n\nconst day = 24 * 60 * 60 * 1000;\n\n/** A product's curated tools as one router. */\nconst mount = <Query, Mutation>(product: {\n  readonly tools: Readonly<Record<string, RouterChild<Query, Mutation>>>;\n  readonly meta: RouterOptions;\n}) =>\n  router(product.tools, product.meta);\n\nexport const curated = (source: Source) => ({\n  accounts: query(\n    {\n      description: \"List the linked Google accounts by address. Tools that take `account` accept one of these addresses.\",\n      input: object({}),\n    },\n    async (ctx: Context) => ({\n      accounts: (await linked(ctx, source)).map((target) => ({ email: target.email, accountId: target.account.id })),\n    }),\n  ),\n  search: query(\n    {\n      description:\n        \"Search everything at once across every linked Google account (or one): mail (Gmail search syntax works), Drive files, calendar events from 90 days back to a year ahead, and contacts. Returns the top matches of each; follow up with the product's own tools.\",\n      input: object({ query: string({ minLength: 1 }), account: string().optional(), max: number().optional() }),\n    },\n    async (ctx: Context, input) => {\n      const targets = await select(ctx, source, input.account);\n      const max = Math.min(Math.max(input.max ?? 5, 1), 25);\n      const now = Date.now();\n      const [mail, files, events, people] = await Promise.all([\n        searchMail(ctx, targets, input.query, max),\n        // Gmail operators (from:, is:unread) mean nothing to Drive; search its words only.\n        searchFiles(ctx, targets, driveQuery(input.query.replace(/\\b[a-z_]+:\\S+/gi, \"\").trim() || input.query, undefined), max),\n        listEvents(ctx, targets, now - 90 * day, now + 365 * day, input.query),\n        fanOut(targets, (target) => findPeople(ctx, target, input.query, max)),\n      ]);\n      return {\n        mail: mail.threads,\n        files: files.files,\n        // Nearest to today first, whether past or upcoming.\n        events: [...events.events].sort((a, b) => Math.abs(Date.parse(a.start) - now) - Math.abs(Date.parse(b.start) - now)).slice(0, max),\n        people: people.items.slice(0, max),\n        errors: [...mail.errors, ...files.errors, ...events.errors, ...people.errors],\n      };\n    },\n  ),\n  gmail: mount(gmail(source)),\n  calendar: mount(calendar(source)),\n  drive: mount(drive(source)),\n  sheets: mount(sheets(source)),\n  contacts: mount(contacts(source)),\n  tasks: mount(tasks(source)),\n});\n"},{"path":"icon.ts","content":"import type { AppIcon } from \"apps\";\n\n// Generated by scripts/icon.ts from the vendor's logo.\nexport const icons: readonly AppIcon[] = [\n  {\n    \"src\": \"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMTgiIGhlaWdodD0iMTIwIiB2aWV3Qm94PSIwIDAgMTE4IDEyMCI+PHRpdGxlPmdvb2dsZV9idXR0bjwvdGl0bGU+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48cGF0aCBmaWxsPSIjNDI4NWY0IiBkPSJNMTE3LjYgNjEuMzY0YzAtNC4yNTUtLjM4Mi04LjM0Ni0xLjA5LTEyLjI3M0g2MFY3Mi4zaDMyLjI5Yy0xLjM5IDcuNS01LjYxNyAxMy44NTUtMTEuOTcyIDE4LjExdjE1LjA1NEg5OS43MWMxMS4zNDYtMTAuNDQ2IDE3Ljg5MS0yNS44MjggMTcuODkxLTQ0LjEiLz48cGF0aCBmaWxsPSIjMzRhODUzIiBkPSJNNjAgMTIwYzE2LjIgMCAyOS43ODItNS4zNzMgMzkuNzEtMTQuNTM2TDgwLjMxNyA5MC40MDljLTUuMzczIDMuNi0xMi4yNDUgNS43MjctMjAuMzE4IDUuNzI3LTE1LjYyNyAwLTI4Ljg1NS0xMC41NTQtMzMuNTczLTI0LjczNkg2LjM4MnYxNS41NDVDMTYuMjU1IDEwNi41NTUgMzYuNTQ1IDEyMCA2MCAxMjAiLz48cGF0aCBmaWxsPSIjZmJiYzA1IiBkPSJNMjYuNDI3IDcxLjRjLTEuMi0zLjYtMS44ODItNy40NDUtMS44ODItMTEuNHMuNjgyLTcuOCAxLjg4Mi0xMS40VjMzLjA1NUg2LjM4MkE2MCA2MCAwIDAgMCAwIDYwYTYwIDYwIDAgMCAwIDYuMzgyIDI2Ljk0NXoiLz48cGF0aCBmaWxsPSIjZWE0MzM1IiBkPSJNNjAgMjMuODY0YzguODEgMCAxNi43MTggMy4wMjcgMjIuOTM2IDguOTcybDE3LjIxLTE3LjIwOUM4OS43NTQgNS45NDUgNzYuMTcyIDAgNjAgMCAzNi41NDUgMCAxNi4yNTUgMTMuNDQ1IDYuMzgyIDMzLjA1NUwyNi40MjcgNDguNkMzMS4xNDUgMzQuNDE4IDQ0LjM3MyAyMy44NjQgNjAgMjMuODY0Ii8+PHBhdGggZD0iTTAgMGgxMjB2MTIwSDB6Ii8+PC9nPjwvc3ZnPg==\",\n    \"mimeType\": \"image/svg+xml\"\n  }\n];\n"},{"path":"index.ts","content":"import { accountRouter, defineApp, router, withApprovals, type RouterDeclaration } from \"apps\";\nimport { always } from \"apps/operations/approval\";\nimport { liveOpenapiRouter, type OpenapiToolNamesOptions } from \"apps/openapi\";\nimport { icons } from \"./icon.js\";\nimport { requirements } from \"./provider.js\";\nimport { curated } from \"./curated.js\";\nimport { addresses } from \"./tools/shared.js\";\n// products/ holds copies of the single-product packages' sources (scripts/google-vendor.ts).\nimport { options as calendar } from \"./products/calendar/openapi.js\";\nimport { options as contacts } from \"./products/contacts/openapi.js\";\nimport * as docs from \"./products/docs/tools.js\";\nimport { options as drive } from \"./products/drive/openapi.js\";\nimport { options as forms } from \"./products/forms/openapi.js\";\nimport { options as gmail } from \"./products/gmail/openapi.js\";\nimport * as meet from \"./products/meet/tools.js\";\nimport { libraryOptions as photosLibrary, pickerOptions as photosPicker } from \"./products/photos/openapi.js\";\nimport { options as sheets } from \"./products/sheets/openapi.js\";\nimport * as slides from \"./products/slides/tools.js\";\nimport { options as tasks } from \"./products/tasks/openapi.js\";\n\nconst approve = <Query, Mutation>(tools: RouterDeclaration<Query, Mutation>) =>\n  withApprovals(tools, (tool) => (tool.kind === \"mutation\" ? always() : undefined));\n\nexport default defineApp(\n  { ...requirements, icons },\n  async ({ user, cache, fetch, signal }) => ({\n    tools: router(\n      {\n        ...curated({\n          accounts: user?.accounts.google ?? [],\n          address: addresses.userinfo(\"https://www.googleapis.com/oauth2/v3/userinfo\"),\n          api: (product) => `api.${product}`,\n        }),\n        api: router(\n          await accountRouter(\n            user?.accounts.google ?? [],\n            (account) => {\n              const token = account.fields.access_token;\n              const openapi = (options: OpenapiToolNamesOptions) =>\n                approve(liveOpenapiRouter({ ...options, cache, fetch, signal, account }));\n              return router({\n                gmail: router(openapi(gmail), {\n                  title: \"Gmail\",\n                  description: \"Messages, threads, drafts, labels, history, filters, send-as aliases and settings.\",\n                }),\n                calendar: router(openapi(calendar), {\n                  title: \"Google Calendar\",\n                  description: \"Calendars, events, attendees, free/busy availability, sharing and settings.\",\n                }),\n                drive: router(openapi(drive), {\n                  title: \"Google Drive\",\n                  description: \"Files, folders, shared drives, permissions, comments, replies and revisions.\",\n                }),\n                sheets: router(openapi(sheets), {\n                  title: \"Google Sheets\",\n                  description: \"Spreadsheets, sheets, cell values, formatting and batch updates.\",\n                }),\n                docs: router(approve(docs.tools(token, fetch, signal)), docs.meta),\n                slides: router(approve(slides.tools(token, fetch, signal)), slides.meta),\n                forms: router(openapi(forms), {\n                  title: \"Google Forms\",\n                  description: \"Forms, questions, settings and responses.\",\n                }),\n                tasks: router(openapi(tasks), {\n                  title: \"Google Tasks\",\n                  description: \"Task lists and tasks.\",\n                }),\n                contacts: router(openapi(contacts), {\n                  title: \"Google Contacts\",\n                  description: \"Contacts, contact groups, other contacts and the Workspace directory (People API).\",\n                }),\n                meet: router(approve(meet.tools(token, fetch, signal)), meet.meta),\n                photos: router(\n                  {\n                    library: router(openapi(photosLibrary), {\n                      title: \"Google Photos Library\",\n                      description: \"Albums and media items created by this app; uploads into the library.\",\n                    }),\n                    picker: router(openapi(photosPicker), {\n                      title: \"Google Photos Picker\",\n                      description: \"Picker sessions where the user selects photos, then the picked items.\",\n                    }),\n                  },\n                  { title: \"Google Photos\", description: \"Google Photos Library and Picker APIs.\" },\n                ),\n              });\n            },\n            { signal },\n          ),\n          {\n            title: \"Google APIs\",\n            description:\n              \"The complete APIs of each Google product, per account: every tool takes accountId (from the top-level accounts tool) and the API's own input.\",\n          },\n        ),\n      },\n      {\n        title: \"Google\",\n        description:\n          \"Every linked Google account across Gmail, Calendar, Drive, Sheets, Docs, Slides, Forms, Tasks, Contacts, Meet and Photos.\",\n        instructions:\n          \"Start with the top-level tools: search, gmail, calendar, drive, sheets, contacts and tasks read across every linked account at once unless `account` (an address) narrows them, and their results name the account each item came from. Pass that account to reads and writes of one item. Use api.<product> only for what the curated tools do not cover.\",\n        icons,\n      },\n    ),\n  }),\n);\n"},{"path":"package.json","content":"{\n  \"name\": \"@executor.sh/google\",\n  \"description\": \"Every linked Google account across Gmail, Calendar, Drive, Sheets, Docs, Slides, Forms, Tasks, Contacts, Meet and Photos: cross-account search, agenda and availability, plus the complete APIs.\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"executor\": {\n    \"title\": \"Google\"\n  },\n  \"dependencies\": {\n    \"apps\": \"0.0.1-beta.100\"\n  }\n}\n"},{"path":"products/calendar/calendar-openapi.json","content":"{\n \"openapi\": \"3.0.3\",\n \"info\": {\n  \"title\": \"Calendar API\",\n  \"version\": \"v3 (discovery revision 20261005)\",\n  \"description\": \"Manipulates events and other calendar data.\"\n },\n \"servers\": [\n  {\n   \"url\": \"https://www.googleapis.com/calendar/v3\"\n  }\n ],\n \"security\": [\n  {\n   \"bearer\": []\n  }\n ],\n \"paths\": {\n  \"/calendars/{calendarId}/events/{eventId}\": {\n   \"put\": {\n    \"operationId\": \"calendar.events.update\",\n    \"description\": \"Updates an event.\",\n    \"parameters\": [\n     {\n      \"name\": \"alwaysIncludeEmail\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated and ignored. A value will always be returned in the email field for the organizer, creator and attendees, even if no real email address is available (i.e. a generated, non-working value will be provided).\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"eventLabelVersion\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Version number of the event label feature supported by the API client. Version 0 assumes no event label support and processes the colorId field for color management. Version 1 enables support for event labels, and processes the eventLabelId in the event's body. In this case, the colorId field is ignored. The default is 0.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"supportsAttachments\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether API client performing operation supports event attachments. Optional. The default is False.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"maxAttendees\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The maximum number of attendees to include in the response. If there are more than the specified number of attendees, only the participant is returned. Optional.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"conferenceDataVersion\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Version number of conference data supported by the API client. Version 0 assumes no conference data support and ignores conference data in the event's body. Version 1 enables support for copying of ConferenceData as well as for creating new conferences using the createRequest field of conferenceData. The default is 0.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"sendNotifications\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated. Please use sendUpdates instead.\\n\\nWhether to send notifications about the event update (for example, description changes, etc.). Note that some emails might still be sent even if you set the value to false. The default is false.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"eventId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Event identifier.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"sendUpdates\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Guests who should receive notifications about the event update (for example, title changes, etc.).\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"enum\": [\n        \"all\",\n        \"externalOnly\",\n        \"none\"\n       ]\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Event\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Event\"\n       }\n      }\n     }\n    }\n   },\n   \"patch\": {\n    \"operationId\": \"calendar.events.patch\",\n    \"description\": \"Updates an event. This method supports patch semantics.\",\n    \"parameters\": [\n     {\n      \"name\": \"supportsAttachments\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether API client performing operation supports event attachments. Optional. The default is False.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"alwaysIncludeEmail\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated and ignored. A value will always be returned in the email field for the organizer, creator and attendees, even if no real email address is available (i.e. a generated, non-working value will be provided).\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"sendUpdates\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Guests who should receive notifications about the event update (for example, title changes, etc.).\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"enum\": [\n        \"all\",\n        \"externalOnly\",\n        \"none\"\n       ]\n      }\n     },\n     {\n      \"name\": \"maxAttendees\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The maximum number of attendees to include in the response. If there are more than the specified number of attendees, only the participant is returned. Optional.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"sendNotifications\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated. Please use sendUpdates instead.\\n\\nWhether to send notifications about the event update (for example, description changes, etc.). Note that some emails might still be sent even if you set the value to false. The default is false.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"eventLabelVersion\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Version number of the event label feature supported by the API client. Version 0 assumes no event label support and processes the colorId field for color management. Version 1 enables support for event labels, and processes the eventLabelId in the event's body. In this case, the colorId field is ignored. The default is 0.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"eventId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Event identifier.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"conferenceDataVersion\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Version number of conference data supported by the API client. Version 0 assumes no conference data support and ignores conference data in the event's body. Version 1 enables support for copying of ConferenceData as well as for creating new conferences using the createRequest field of conferenceData. The default is 0.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Event\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Event\"\n       }\n      }\n     }\n    }\n   },\n   \"delete\": {\n    \"operationId\": \"calendar.events.delete\",\n    \"description\": \"Deletes an event.\",\n    \"parameters\": [\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"eventId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Event identifier.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"sendUpdates\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Guests who should receive notifications about the deletion of the event.\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"enum\": [\n        \"all\",\n        \"externalOnly\",\n        \"none\"\n       ]\n      }\n     },\n     {\n      \"name\": \"sendNotifications\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated. Please use sendUpdates instead.\\n\\nWhether to send notifications about the deletion of the event. Note that some emails might still be sent even if you set the value to false. The default is false.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\"\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   },\n   \"get\": {\n    \"operationId\": \"calendar.events.get\",\n    \"description\": \"Returns an event based on its Google Calendar ID. To retrieve an event using its iCalendar ID, call the events.list method using the iCalUID parameter.\",\n    \"parameters\": [\n     {\n      \"name\": \"timeZone\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Time zone used in the response. Optional. The default is the time zone of the calendar.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"alwaysIncludeEmail\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated and ignored. A value will always be returned in the email field for the organizer, creator and attendees, even if no real email address is available (i.e. a generated, non-working value will be provided).\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"eventId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Event identifier.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"maxAttendees\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The maximum number of attendees to include in the response. If there are more than the specified number of attendees, only the participant is returned. Optional.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Event\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/calendars/{calendarId}/events/{eventId}/instances\": {\n   \"get\": {\n    \"operationId\": \"calendar.events.instances\",\n    \"description\": \"Returns instances of the specified recurring event.\",\n    \"parameters\": [\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Token specifying which result page to return. Optional.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"timeMax\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Upper bound (exclusive) for an event's start time to filter by. Optional. The default is not to filter by start time. Must be an RFC3339 timestamp with mandatory time zone offset.\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"date-time\"\n      }\n     },\n     {\n      \"name\": \"eventId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Recurring event identifier.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"timeMin\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Lower bound (inclusive) for an event's end time to filter by. Optional. The default is not to filter by end time. Must be an RFC3339 timestamp with mandatory time zone offset.\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"date-time\"\n      }\n     },\n     {\n      \"name\": \"showDeleted\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to include deleted events (with status equals \\\"cancelled\\\") in the result. Cancelled instances of recurring events will still be included if singleEvents is False. Optional. The default is False.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"originalStart\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The original start time of the instance in the result. Optional.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"alwaysIncludeEmail\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated and ignored. A value will always be returned in the email field for the organizer, creator and attendees, even if no real email address is available (i.e. a generated, non-working value will be provided).\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"maxResults\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Maximum number of events returned on one result page. By default the value is 250 events. The page size can never be larger than 2500 events. Optional.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"maxAttendees\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The maximum number of attendees to include in the response. If there are more than the specified number of attendees, only the participant is returned. Optional.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"timeZone\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Time zone used in the response. Optional. The default is the time zone of the calendar.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Events\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/calendars/{calendarId}/events/import\": {\n   \"post\": {\n    \"operationId\": \"calendar.events.import\",\n    \"description\": \"Imports an event. This operation is used to add a private copy of an existing event to a calendar. Only events with an eventType of default may be imported.\\nDeprecated behavior: If a non-default event is imported, its type will be changed to default and any event-type-specific properties it may have will be dropped.\",\n    \"parameters\": [\n     {\n      \"name\": \"eventLabelVersion\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Version number of the event label feature supported by the API client. Version 0 assumes no event label support and processes the colorId field for color management. Version 1 enables support for event labels, and processes the eventLabelId in the event's body. In this case, the colorId field is ignored. The default is 0.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"conferenceDataVersion\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Version number of conference data supported by the API client. Version 0 assumes no conference data support and ignores conference data in the event's body. Version 1 enables support for copying of ConferenceData as well as for creating new conferences using the createRequest field of conferenceData. The default is 0.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"supportsAttachments\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether API client performing operation supports event attachments. Optional. The default is False.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Event\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Event\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/calendars/{calendarId}/events\": {\n   \"get\": {\n    \"operationId\": \"calendar.events.list\",\n    \"description\": \"Returns events on the specified calendar.\",\n    \"parameters\": [\n     {\n      \"name\": \"singleEvents\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to expand recurring events into instances and only return single one-off events and instances of recurring events, but not the underlying recurring events themselves. Optional. The default is False.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"syncToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Token obtained from the nextSyncToken field returned on the last page of results from the previous list request. It makes the result of this list request contain only entries that have changed since then. All events deleted since the previous list request will always be in the result set and it is not allowed to set showDeleted to False.\\nThere are several query parameters that cannot be specified together with nextSyncToken to ensure consistency of the client state.\\n\\nThese are: \\n- iCalUID \\n- orderBy \\n- privateExtendedProperty \\n- q \\n- sharedExtendedProperty \\n- timeMin \\n- timeMax \\n- updatedMin All other query parameters should be the same as for the initial synchronization to avoid undefined behavior. If the syncToken expires, the server will respond with a 410 GONE response code and the client should clear its storage and perform a full synchronization without any syncToken.\\nLearn more about incremental synchronization.\\nOptional. The default is to return all entries.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"timeMax\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Upper bound (exclusive) for an event's start time to filter by. Optional. The default is not to filter by start time. Must be an RFC3339 timestamp with mandatory time zone offset, for example, 2011-06-03T10:00:00-07:00, 2011-06-03T10:00:00Z. Milliseconds may be provided but are ignored. If timeMin is set, timeMax must be greater than timeMin.\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"date-time\"\n      }\n     },\n     {\n      \"name\": \"iCalUID\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Specifies an event ID in the iCalendar format to be provided in the response. Optional. Use this if you want to search for an event by its iCalendar ID.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"orderBy\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The order of the events returned in the result. Optional. The default is an unspecified, stable order.\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"enum\": [\n        \"startTime\",\n        \"updated\"\n       ]\n      }\n     },\n     {\n      \"name\": \"showDeleted\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to include deleted events (with status equals \\\"cancelled\\\") in the result. Cancelled instances of recurring events (but not the underlying recurring event) will still be included if showDeleted and singleEvents are both False. If showDeleted and singleEvents are both True, only single instances of deleted events (but not the underlying recurring events) are returned. Optional. The default is False.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Token specifying which result page to return. Optional.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"q\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Free text search terms to find events that match these terms in the following fields:\\n\\n- summary \\n- description \\n- location \\n- attendee's displayName \\n- attendee's email \\n- organizer's displayName \\n- organizer's email \\n- workingLocationProperties.officeLocation.buildingId \\n- workingLocationProperties.officeLocation.deskId \\n- workingLocationProperties.officeLocation.label \\n- workingLocationProperties.customLocation.label \\nThese search terms also match predefined keywords against all display title translations of working location, out-of-office, and focus-time events. For example, searching for \\\"Office\\\" or \\\"Bureau\\\" returns working location events of type officeLocation, whereas searching for \\\"Out of office\\\" or \\\"Abwesend\\\" returns out-of-office events. Optional.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"alwaysIncludeEmail\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated and ignored.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"timeZone\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Time zone used in the response. Optional. The default is the time zone of the calendar.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"privateExtendedProperty\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Extended properties constraint specified as propertyName=value. Matches only private properties. This parameter might be repeated multiple times to return events that match all given constraints.\",\n      \"schema\": {\n       \"type\": \"array\",\n       \"items\": {\n        \"type\": \"string\"\n       }\n      }\n     },\n     {\n      \"name\": \"updatedMin\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Lower bound for an event's last modification time (as a RFC3339 timestamp) to filter by. When specified, entries deleted since this time will always be included regardless of showDeleted. Optional. The default is not to filter by last modification time.\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"date-time\"\n      }\n     },\n     {\n      \"name\": \"sharedExtendedProperty\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Extended properties constraint specified as propertyName=value. Matches only shared properties. This parameter might be repeated multiple times to return events that match all given constraints.\",\n      \"schema\": {\n       \"type\": \"array\",\n       \"items\": {\n        \"type\": \"string\"\n       }\n      }\n     },\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"showHiddenInvitations\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to include hidden invitations in the result. Optional. The default is False.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"maxAttendees\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The maximum number of attendees to include in the response. If there are more than the specified number of attendees, only the participant is returned. Optional.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"eventTypes\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Event types to return. Optional. This parameter can be repeated multiple times to return events of different types. If unset, returns all event types.\",\n      \"schema\": {\n       \"type\": \"array\",\n       \"items\": {\n        \"type\": \"string\",\n        \"enum\": [\n         \"birthday\",\n         \"default\",\n         \"focusTime\",\n         \"fromGmail\",\n         \"outOfOffice\",\n         \"workingLocation\"\n        ]\n       }\n      }\n     },\n     {\n      \"name\": \"timeMin\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Lower bound (exclusive) for an event's end time to filter by. Optional. The default is not to filter by end time. Must be an RFC3339 timestamp with mandatory time zone offset, for example, 2011-06-03T10:00:00-07:00, 2011-06-03T10:00:00Z. Milliseconds may be provided but are ignored. If timeMax is set, timeMin must be smaller than timeMax.\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"date-time\"\n      }\n     },\n     {\n      \"name\": \"maxResults\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Maximum number of events returned on one result page. The number of events in the resulting page may be less than this value, or none at all, even if there are more events matching the query. Incomplete pages can be detected by a non-empty nextPageToken field in the response. By default the value is 250 events. The page size can never be larger than 2500 events. Optional.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Events\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   },\n   \"post\": {\n    \"operationId\": \"calendar.events.insert\",\n    \"description\": \"Creates an event.\",\n    \"parameters\": [\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"supportsAttachments\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether API client performing operation supports event attachments. Optional. The default is False.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"eventLabelVersion\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Version number of the event label feature supported by the API client. Version 0 assumes no event label support and processes the colorId field for color management. Version 1 enables support for event labels, and processes the eventLabelId in the event's body. In this case, the colorId field is ignored. The default is 0.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"sendUpdates\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to send notifications about the creation of the new event. Note that some emails might still be sent. The default is false.\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"enum\": [\n        \"all\",\n        \"externalOnly\",\n        \"none\"\n       ]\n      }\n     },\n     {\n      \"name\": \"conferenceDataVersion\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Version number of conference data supported by the API client. Version 0 assumes no conference data support and ignores conference data in the event's body. Version 1 enables support for copying of ConferenceData as well as for creating new conferences using the createRequest field of conferenceData. The default is 0.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"maxAttendees\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The maximum number of attendees to include in the response. If there are more than the specified number of attendees, only the participant is returned. Optional.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"sendNotifications\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated. Please use sendUpdates instead.\\n\\nWhether to send notifications about the creation of the new event. Note that some emails might still be sent even if you set the value to false. The default is false.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Event\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Event\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/calendars/{calendarId}/events/watch\": {\n   \"post\": {\n    \"operationId\": \"calendar.events.watch\",\n    \"description\": \"Watch for changes to Events resources.\",\n    \"parameters\": [\n     {\n      \"name\": \"privateExtendedProperty\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Extended properties constraint specified as propertyName=value. Matches only private properties. This parameter might be repeated multiple times to return events that match all given constraints.\",\n      \"schema\": {\n       \"type\": \"array\",\n       \"items\": {\n        \"type\": \"string\"\n       }\n      }\n     },\n     {\n      \"name\": \"eventTypes\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Event types to return. Optional. This parameter can be repeated multiple times to return events of different types. If unset, returns all event types.\",\n      \"schema\": {\n       \"type\": \"array\",\n       \"items\": {\n        \"type\": \"string\",\n        \"enum\": [\n         \"birthday\",\n         \"default\",\n         \"focusTime\",\n         \"fromGmail\",\n         \"outOfOffice\",\n         \"workingLocation\"\n        ]\n       }\n      }\n     },\n     {\n      \"name\": \"timeMin\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Lower bound (exclusive) for an event's end time to filter by. Optional. The default is not to filter by end time. Must be an RFC3339 timestamp with mandatory time zone offset, for example, 2011-06-03T10:00:00-07:00, 2011-06-03T10:00:00Z. Milliseconds may be provided but are ignored. If timeMax is set, timeMin must be smaller than timeMax.\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"date-time\"\n      }\n     },\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"singleEvents\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to expand recurring events into instances and only return single one-off events and instances of recurring events, but not the underlying recurring events themselves. Optional. The default is False.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"maxResults\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Maximum number of events returned on one result page. The number of events in the resulting page may be less than this value, or none at all, even if there are more events matching the query. Incomplete pages can be detected by a non-empty nextPageToken field in the response. By default the value is 250 events. The page size can never be larger than 2500 events. Optional.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"q\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Free text search terms to find events that match these terms in the following fields:\\n\\n- summary \\n- description \\n- location \\n- attendee's displayName \\n- attendee's email \\n- organizer's displayName \\n- organizer's email \\n- workingLocationProperties.officeLocation.buildingId \\n- workingLocationProperties.officeLocation.deskId \\n- workingLocationProperties.officeLocation.label \\n- workingLocationProperties.customLocation.label \\nThese search terms also match predefined keywords against all display title translations of working location, out-of-office, and focus-time events. For example, searching for \\\"Office\\\" or \\\"Bureau\\\" returns working location events of type officeLocation, whereas searching for \\\"Out of office\\\" or \\\"Abwesend\\\" returns out-of-office events. Optional.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"iCalUID\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Specifies an event ID in the iCalendar format to be provided in the response. Optional. Use this if you want to search for an event by its iCalendar ID.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"orderBy\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The order of the events returned in the result. Optional. The default is an unspecified, stable order.\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"enum\": [\n        \"startTime\",\n        \"updated\"\n       ]\n      }\n     },\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Token specifying which result page to return. Optional.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"showHiddenInvitations\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to include hidden invitations in the result. Optional. The default is False.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"alwaysIncludeEmail\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated and ignored.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"showDeleted\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to include deleted events (with status equals \\\"cancelled\\\") in the result. Cancelled instances of recurring events (but not the underlying recurring event) will still be included if showDeleted and singleEvents are both False. If showDeleted and singleEvents are both True, only single instances of deleted events (but not the underlying recurring events) are returned. Optional. The default is False.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"timeZone\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Time zone used in the response. Optional. The default is the time zone of the calendar.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"timeMax\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Upper bound (exclusive) for an event's start time to filter by. Optional. The default is not to filter by start time. Must be an RFC3339 timestamp with mandatory time zone offset, for example, 2011-06-03T10:00:00-07:00, 2011-06-03T10:00:00Z. Milliseconds may be provided but are ignored. If timeMin is set, timeMax must be greater than timeMin.\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"date-time\"\n      }\n     },\n     {\n      \"name\": \"sharedExtendedProperty\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Extended properties constraint specified as propertyName=value. Matches only shared properties. This parameter might be repeated multiple times to return events that match all given constraints.\",\n      \"schema\": {\n       \"type\": \"array\",\n       \"items\": {\n        \"type\": \"string\"\n       }\n      }\n     },\n     {\n      \"name\": \"syncToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Token obtained from the nextSyncToken field returned on the last page of results from the previous list request. It makes the result of this list request contain only entries that have changed since then. All events deleted since the previous list request will always be in the result set and it is not allowed to set showDeleted to False.\\nThere are several query parameters that cannot be specified together with nextSyncToken to ensure consistency of the client state.\\n\\nThese are: \\n- iCalUID \\n- orderBy \\n- privateExtendedProperty \\n- q \\n- sharedExtendedProperty \\n- timeMin \\n- timeMax \\n- updatedMin All other query parameters should be the same as for the initial synchronization to avoid undefined behavior. If the syncToken expires, the server will respond with a 410 GONE response code and the client should clear its storage and perform a full synchronization without any syncToken.\\nLearn more about incremental synchronization.\\nOptional. The default is to return all entries.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"updatedMin\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Lower bound for an event's last modification time (as a RFC3339 timestamp) to filter by. When specified, entries deleted since this time will always be included regardless of showDeleted. Optional. The default is not to filter by last modification time.\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"date-time\"\n      }\n     },\n     {\n      \"name\": \"maxAttendees\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The maximum number of attendees to include in the response. If there are more than the specified number of attendees, only the participant is returned. Optional.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Channel\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Channel\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/calendars/{calendarId}/events/{eventId}/move\": {\n   \"post\": {\n    \"operationId\": \"calendar.events.move\",\n    \"description\": \"Moves an event to another calendar, i.e. changes an event's organizer. Note that only default events can be moved; birthday, focusTime, fromGmail, outOfOffice and workingLocation events cannot be moved.\",\n    \"parameters\": [\n     {\n      \"name\": \"sendUpdates\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Guests who should receive notifications about the change of the event's organizer.\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"enum\": [\n        \"all\",\n        \"externalOnly\",\n        \"none\"\n       ]\n      }\n     },\n     {\n      \"name\": \"sendNotifications\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated. Please use sendUpdates instead.\\n\\nWhether to send notifications about the change of the event's organizer. Note that some emails might still be sent even if you set the value to false. The default is false.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"eventId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Event identifier.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier of the source calendar where the event currently is on.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"destination\",\n      \"in\": \"query\",\n      \"required\": true,\n      \"description\": \"Calendar identifier of the target calendar where the event is to be moved to.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Event\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/calendars/{calendarId}/events/quickAdd\": {\n   \"post\": {\n    \"operationId\": \"calendar.events.quickAdd\",\n    \"description\": \"Creates an event based on a simple text string.\",\n    \"parameters\": [\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"sendNotifications\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated. Please use sendUpdates instead.\\n\\nWhether to send notifications about the creation of the event. Note that some emails might still be sent even if you set the value to false. The default is false.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"sendUpdates\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Guests who should receive notifications about the creation of the new event.\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"enum\": [\n        \"all\",\n        \"externalOnly\",\n        \"none\"\n       ]\n      }\n     },\n     {\n      \"name\": \"text\",\n      \"in\": \"query\",\n      \"required\": true,\n      \"description\": \"The text describing the event to be created.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Event\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/freeBusy\": {\n   \"post\": {\n    \"operationId\": \"calendar.freebusy.query\",\n    \"description\": \"Returns free/busy information for a set of calendars.\",\n    \"parameters\": [\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/FreeBusyResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/FreeBusyRequest\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/users/me/calendarList\": {\n   \"post\": {\n    \"operationId\": \"calendar.calendarList.insert\",\n    \"description\": \"Inserts an existing calendar into the user's calendar list.\",\n    \"parameters\": [\n     {\n      \"name\": \"colorRgbFormat\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to use the foregroundColor and backgroundColor fields to write the calendar colors (RGB). If this feature is used, the index-based colorId field will be set to the best matching option automatically. Optional. The default is False.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/CalendarListEntry\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/CalendarListEntry\"\n       }\n      }\n     }\n    }\n   },\n   \"get\": {\n    \"operationId\": \"calendar.calendarList.list\",\n    \"description\": \"Returns the calendars on the user's calendar list.\",\n    \"parameters\": [\n     {\n      \"name\": \"maxResults\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Maximum number of entries returned on one result page. By default the value is 100 entries. The page size can never be larger than 250 entries. Optional.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"showDeleted\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to include deleted calendar list entries in the result. Optional. The default is False.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"showOwnOrganizationOnly\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to show only entries for calendars from the organization. This parameter is only applicable to Google Workspace users. Optional. The default is False.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Token specifying which result page to return. Optional.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"syncToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Token obtained from the nextSyncToken field returned on the last page of results from the previous list request. It makes the result of this list request contain only entries that have changed since then. If only read-only fields such as calendar properties or ACLs have changed, the entry won't be returned. All entries deleted and hidden since the previous list request will always be in the result set and it is not allowed to set showDeleted neither showHidden to False.\\nTo ensure client state consistency minAccessRole and showOwnOrganizationOnly query parameters cannot be specified together with nextSyncToken.\\nIf the syncToken expires, the server will respond with a 410 GONE response code and the client should clear its storage and perform a full synchronization without any syncToken.\\nLearn more about incremental synchronization.\\nOptional. The default is to return all entries.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"minAccessRole\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The minimum access role for the user in the returned entries. Optional. The default is no restriction.\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"enum\": [\n        \"freeBusyReader\",\n        \"owner\",\n        \"reader\",\n        \"writer\",\n        \"writerWithoutPrivateAccess\"\n       ]\n      }\n     },\n     {\n      \"name\": \"showHidden\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to show hidden entries. Optional. The default is False.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/CalendarList\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/users/me/calendarList/{calendarId}\": {\n   \"put\": {\n    \"operationId\": \"calendar.calendarList.update\",\n    \"description\": \"Updates an existing calendar on the user's calendar list.\",\n    \"parameters\": [\n     {\n      \"name\": \"colorRgbFormat\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to use the foregroundColor and backgroundColor fields to write the calendar colors (RGB). If this feature is used, the index-based colorId field will be set to the best matching option automatically. Optional. The default is False.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/CalendarListEntry\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/CalendarListEntry\"\n       }\n      }\n     }\n    }\n   },\n   \"patch\": {\n    \"operationId\": \"calendar.calendarList.patch\",\n    \"description\": \"Updates an existing calendar on the user's calendar list. This method supports patch semantics.\",\n    \"parameters\": [\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"colorRgbFormat\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to use the foregroundColor and backgroundColor fields to write the calendar colors (RGB). If this feature is used, the index-based colorId field will be set to the best matching option automatically. Optional. The default is False.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/CalendarListEntry\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/CalendarListEntry\"\n       }\n      }\n     }\n    }\n   },\n   \"get\": {\n    \"operationId\": \"calendar.calendarList.get\",\n    \"description\": \"Returns a calendar from the user's calendar list.\",\n    \"parameters\": [\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/CalendarListEntry\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   },\n   \"delete\": {\n    \"operationId\": \"calendar.calendarList.delete\",\n    \"description\": \"Removes a calendar from the user's calendar list.\",\n    \"parameters\": [\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\"\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/users/me/calendarList/watch\": {\n   \"post\": {\n    \"operationId\": \"calendar.calendarList.watch\",\n    \"description\": \"Watch for changes to CalendarList resources.\",\n    \"parameters\": [\n     {\n      \"name\": \"showOwnOrganizationOnly\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to show only entries for calendars from the organization. This parameter is only applicable to Google Workspace users. Optional. The default is False.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"maxResults\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Maximum number of entries returned on one result page. By default the value is 100 entries. The page size can never be larger than 250 entries. Optional.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"minAccessRole\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The minimum access role for the user in the returned entries. Optional. The default is no restriction.\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"enum\": [\n        \"freeBusyReader\",\n        \"owner\",\n        \"reader\",\n        \"writer\",\n        \"writerWithoutPrivateAccess\"\n       ]\n      }\n     },\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Token specifying which result page to return. Optional.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"syncToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Token obtained from the nextSyncToken field returned on the last page of results from the previous list request. It makes the result of this list request contain only entries that have changed since then. If only read-only fields such as calendar properties or ACLs have changed, the entry won't be returned. All entries deleted and hidden since the previous list request will always be in the result set and it is not allowed to set showDeleted neither showHidden to False.\\nTo ensure client state consistency minAccessRole and showOwnOrganizationOnly query parameters cannot be specified together with nextSyncToken.\\nIf the syncToken expires, the server will respond with a 410 GONE response code and the client should clear its storage and perform a full synchronization without any syncToken.\\nLearn more about incremental synchronization.\\nOptional. The default is to return all entries.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"showDeleted\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to include deleted calendar list entries in the result. Optional. The default is False.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"showHidden\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to show hidden entries. Optional. The default is False.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Channel\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Channel\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/calendars/{calendarId}/acl\": {\n   \"get\": {\n    \"operationId\": \"calendar.acl.list\",\n    \"description\": \"Returns the rules in the access control list for the calendar.\",\n    \"parameters\": [\n     {\n      \"name\": \"maxResults\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Maximum number of entries returned on one result page. By default the value is 100 entries. The page size can never be larger than 250 entries. Optional.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Token specifying which result page to return. Optional.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"syncToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Token obtained from the nextSyncToken field returned on the last page of results from the previous list request. It makes the result of this list request contain only entries that have changed since then. All entries deleted since the previous list request will always be in the result set and it is not allowed to set showDeleted to False.\\nIf the syncToken expires, the server will respond with a 410 GONE response code and the client should clear its storage and perform a full synchronization without any syncToken.\\nLearn more about incremental synchronization.\\nOptional. The default is to return all entries.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"showDeleted\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to include deleted ACLs in the result. Deleted ACLs are represented by role equal to \\\"none\\\". Deleted ACLs will always be included if syncToken is provided. Optional. The default is False.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Acl\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   },\n   \"post\": {\n    \"operationId\": \"calendar.acl.insert\",\n    \"description\": \"Creates an access control rule.\",\n    \"parameters\": [\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"sendNotifications\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to send notifications about the calendar sharing change. Optional. The default is True.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/AclRule\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/AclRule\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/calendars/{calendarId}/acl/{ruleId}\": {\n   \"delete\": {\n    \"operationId\": \"calendar.acl.delete\",\n    \"description\": \"Deletes an access control rule.\",\n    \"parameters\": [\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"ruleId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"ACL rule identifier.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\"\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   },\n   \"get\": {\n    \"operationId\": \"calendar.acl.get\",\n    \"description\": \"Returns an access control rule.\",\n    \"parameters\": [\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"ruleId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"ACL rule identifier.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/AclRule\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   },\n   \"patch\": {\n    \"operationId\": \"calendar.acl.patch\",\n    \"description\": \"Updates an access control rule. This method supports patch semantics.\",\n    \"parameters\": [\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"sendNotifications\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to send notifications about the calendar sharing change. Note that there are no notifications on access removal. Optional. The default is True.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"ruleId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"ACL rule identifier.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/AclRule\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/AclRule\"\n       }\n      }\n     }\n    }\n   },\n   \"put\": {\n    \"operationId\": \"calendar.acl.update\",\n    \"description\": \"Updates an access control rule.\",\n    \"parameters\": [\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"sendNotifications\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to send notifications about the calendar sharing change. Note that there are no notifications on access removal. Optional. The default is True.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"ruleId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"ACL rule identifier.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/AclRule\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/AclRule\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/calendars/{calendarId}/acl/watch\": {\n   \"post\": {\n    \"operationId\": \"calendar.acl.watch\",\n    \"description\": \"Watch for changes to ACL resources.\",\n    \"parameters\": [\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"showDeleted\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to include deleted ACLs in the result. Deleted ACLs are represented by role equal to \\\"none\\\". Deleted ACLs will always be included if syncToken is provided. Optional. The default is False.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Token specifying which result page to return. Optional.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"syncToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Token obtained from the nextSyncToken field returned on the last page of results from the previous list request. It makes the result of this list request contain only entries that have changed since then. All entries deleted since the previous list request will always be in the result set and it is not allowed to set showDeleted to False.\\nIf the syncToken expires, the server will respond with a 410 GONE response code and the client should clear its storage and perform a full synchronization without any syncToken.\\nLearn more about incremental synchronization.\\nOptional. The default is to return all entries.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"maxResults\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Maximum number of entries returned on one result page. By default the value is 100 entries. The page size can never be larger than 250 entries. Optional.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Channel\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Channel\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/colors\": {\n   \"get\": {\n    \"operationId\": \"calendar.colors.get\",\n    \"description\": \"Returns the color definitions for calendars and events.\",\n    \"parameters\": [\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Colors\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/channels/stop\": {\n   \"post\": {\n    \"operationId\": \"calendar.channels.stop\",\n    \"description\": \"Stop watching resources through this channel\",\n    \"parameters\": [\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\"\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Channel\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/calendars/{calendarId}/clear\": {\n   \"post\": {\n    \"operationId\": \"calendar.calendars.clear\",\n    \"description\": \"Clears a primary calendar. This operation deletes all events associated with the primary calendar of an account.\",\n    \"parameters\": [\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\"\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/calendars/{calendarId}\": {\n   \"delete\": {\n    \"operationId\": \"calendar.calendars.delete\",\n    \"description\": \"Deletes a secondary calendar. Use calendars.clear for clearing all events on primary calendars.\",\n    \"parameters\": [\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\"\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   },\n   \"get\": {\n    \"operationId\": \"calendar.calendars.get\",\n    \"description\": \"Returns metadata for a calendar.\",\n    \"parameters\": [\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Calendar\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   },\n   \"patch\": {\n    \"operationId\": \"calendar.calendars.patch\",\n    \"description\": \"Updates metadata for a calendar. This method supports patch semantics.\",\n    \"parameters\": [\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Calendar\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Calendar\"\n       }\n      }\n     }\n    }\n   },\n   \"put\": {\n    \"operationId\": \"calendar.calendars.update\",\n    \"description\": \"Updates metadata for a calendar.\",\n    \"parameters\": [\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs call the calendarList.list method. If you want to access the primary calendar of the currently logged in user, use the \\\"primary\\\" keyword.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Calendar\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Calendar\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/calendars/{calendarId}/transferOwnership\": {\n   \"post\": {\n    \"operationId\": \"calendar.calendars.transferOwnership\",\n    \"description\": \"Transfers a secondary calendar between users within a Google Workspace organization. Requires user authentication with Manage Calendars administrator privilege, and one of the following authorization scopes: \\n- https://www.googleapis.com/auth/calendar \\n- https://www.googleapis.com/auth/calendar.calendars In the request, set useAdminAccess to true. The secondary calendar must be active to be transferred. Transferring disabled or deleted calendars isn't supported.\",\n    \"parameters\": [\n     {\n      \"name\": \"calendarId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Calendar identifier. To retrieve calendar IDs, call the calendarList.list method.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"newDataOwner\",\n      \"in\": \"query\",\n      \"required\": true,\n      \"description\": \"The email address of a user who will become the data owner of the calendar.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"useAdminAccess\",\n      \"in\": \"query\",\n      \"required\": true,\n      \"description\": \"When true, the method runs using the user's Google Workspace administrator privileges. The calling user must be a Google Workspace administrator with the Manage Calendars privilege. This method currently only supports admin access, thus only true is accepted for this field.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\"\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/calendars\": {\n   \"post\": {\n    \"operationId\": \"calendar.calendars.insert\",\n    \"description\": \"Creates a secondary calendar.\\nThe authenticated user for the request is made the data owner of the new calendar.\\n\\nNote: We recommend to authenticate as the intended data owner of the calendar. You can use domain-wide delegation of authority to allow applications to act on behalf of a specific user. Don't use a service account for authentication. If you use a service account for authentication, the service account is the data owner, which can lead to unexpected behavior. For example, if a service account is the data owner, data ownership cannot be transferred.\",\n    \"parameters\": [\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Calendar\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Calendar\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/users/me/settings\": {\n   \"get\": {\n    \"operationId\": \"calendar.settings.list\",\n    \"description\": \"Returns all user settings for the authenticated user.\",\n    \"parameters\": [\n     {\n      \"name\": \"maxResults\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Maximum number of entries returned on one result page. By default the value is 100 entries. The page size can never be larger than 250 entries. Optional.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Token specifying which result page to return. Optional.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"syncToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Token obtained from the nextSyncToken field returned on the last page of results from the previous list request. It makes the result of this list request contain only entries that have changed since then.\\nIf the syncToken expires, the server will respond with a 410 GONE response code and the client should clear its storage and perform a full synchronization without any syncToken.\\nLearn more about incremental synchronization.\\nOptional. The default is to return all entries.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Settings\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/users/me/settings/{setting}\": {\n   \"get\": {\n    \"operationId\": \"calendar.settings.get\",\n    \"description\": \"Returns a single user setting.\",\n    \"parameters\": [\n     {\n      \"name\": \"setting\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The id of the user setting.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Setting\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/users/me/settings/watch\": {\n   \"post\": {\n    \"operationId\": \"calendar.settings.watch\",\n    \"description\": \"Watch for changes to Settings resources.\",\n    \"parameters\": [\n     {\n      \"name\": \"maxResults\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Maximum number of entries returned on one result page. By default the value is 100 entries. The page size can never be larger than 250 entries. Optional.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Token specifying which result page to return. Optional.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"syncToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Token obtained from the nextSyncToken field returned on the last page of results from the previous list request. It makes the result of this list request contain only entries that have changed since then.\\nIf the syncToken expires, the server will respond with a 410 GONE response code and the client should clear its storage and perform a full synchronization without any syncToken.\\nLearn more about incremental synchronization.\\nOptional. The default is to return all entries.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Channel\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Channel\"\n       }\n      }\n     }\n    }\n   }\n  }\n },\n \"components\": {\n  \"schemas\": {\n   \"Error\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"domain\": {\n      \"description\": \"Domain, or broad category, of the error.\",\n      \"type\": \"string\"\n     },\n     \"reason\": {\n      \"description\": \"Specific reason for the error. Some of the possible values are:  \\n- \\\"groupTooBig\\\" - The group of users requested is too large for a single query. \\n- \\\"tooManyCalendarsRequested\\\" - The number of calendars requested is too large for a single query. \\n- \\\"notFound\\\" - The requested resource was not found. \\n- \\\"internalError\\\" - The API service has encountered an internal error.  Additional error types may be added in the future, so clients should gracefully handle additional error statuses not included in this list.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"Settings\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"nextPageToken\": {\n      \"description\": \"Token used to access the next page of this result. Omitted if no further results are available, in which case nextSyncToken is provided.\",\n      \"type\": \"string\"\n     },\n     \"nextSyncToken\": {\n      \"description\": \"Token used at a later point in time to retrieve only the entries that have changed since this result was returned. Omitted if further results are available, in which case nextPageToken is provided.\",\n      \"type\": \"string\"\n     },\n     \"kind\": {\n      \"description\": \"Type of the collection (\\\"calendar#settings\\\").\",\n      \"type\": \"string\"\n     },\n     \"items\": {\n      \"description\": \"List of user settings.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Setting\"\n      }\n     },\n     \"etag\": {\n      \"description\": \"Etag of the collection.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"EventOutOfOfficeProperties\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"autoDeclineMode\": {\n      \"description\": \"Whether to decline meeting invitations which overlap Out of office events. Valid values are declineNone, meaning that no meeting invitations are declined; declineAllConflictingInvitations, meaning that all conflicting meeting invitations that conflict with the event are declined; and declineOnlyNewConflictingInvitations, meaning that only new conflicting meeting invitations which arrive while the Out of office event is present are to be declined.\",\n      \"type\": \"string\"\n     },\n     \"declineMessage\": {\n      \"description\": \"Response message to set if an existing event or new invitation is automatically declined by Calendar.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"EventLabel\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"backgroundColor\": {\n      \"description\": \"Background color of the label in hexadecimal format, such as \\\"#039be5\\\". Events with this label are displayed in this color. Required.\",\n      \"type\": \"string\"\n     },\n     \"name\": {\n      \"description\": \"Name of the label. Optional.\\nIf provided this must have at most 50 characters.\",\n      \"type\": \"string\"\n     },\n     \"id\": {\n      \"description\": \"The ID of the label. Optional when inserting a new label. If not provided, a unique ID will be generated. Required when updating a label.\\nIf provided, the ID must be unique within the calendar and follow UUID format.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"Channel\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"resourceId\": {\n      \"description\": \"An opaque ID that identifies the resource being watched on this channel. Stable across different API versions.\",\n      \"type\": \"string\"\n     },\n     \"id\": {\n      \"description\": \"A UUID or similar unique string that identifies this channel.\",\n      \"type\": \"string\"\n     },\n     \"resourceUri\": {\n      \"description\": \"A version-specific identifier for the watched resource.\",\n      \"type\": \"string\"\n     },\n     \"params\": {\n      \"description\": \"Additional parameters controlling delivery channel behavior. Optional.\",\n      \"type\": \"object\",\n      \"additionalProperties\": {\n       \"description\": \"Declares a new parameter by name.\",\n       \"type\": \"string\"\n      }\n     },\n     \"token\": {\n      \"description\": \"An arbitrary string delivered to the target address with each notification delivered over this channel. Optional.\",\n      \"type\": \"string\"\n     },\n     \"address\": {\n      \"description\": \"The address where notifications are delivered for this channel.\",\n      \"type\": \"string\"\n     },\n     \"payload\": {\n      \"description\": \"A Boolean value to indicate whether payload is wanted. Optional.\",\n      \"type\": \"boolean\"\n     },\n     \"expiration\": {\n      \"description\": \"Date and time of notification channel expiration, expressed as a Unix timestamp, in milliseconds. Optional.\",\n      \"type\": \"string\",\n      \"format\": \"int64\"\n     },\n     \"kind\": {\n      \"description\": \"Identifies this as a notification channel used to watch for changes to a resource, which is \\\"api#channel\\\".\",\n      \"type\": \"string\"\n     },\n     \"type\": {\n      \"description\": \"The type of delivery mechanism used for this channel. Valid values are \\\"web_hook\\\" (or \\\"webhook\\\"). Both values refer to a channel where Http requests are used to deliver messages.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"EventAttachment\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"fileUrl\": {\n      \"description\": \"URL link to the attachment.\\nFor adding Google Drive file attachments use the same format as in alternateLink property of the Files resource in the Drive API.\\nRequired when adding an attachment.\",\n      \"type\": \"string\"\n     },\n     \"iconLink\": {\n      \"description\": \"URL link to the attachment's icon. This field can only be modified for custom third-party attachments.\",\n      \"type\": \"string\"\n     },\n     \"mimeType\": {\n      \"description\": \"Internet media type (MIME type) of the attachment.\",\n      \"type\": \"string\"\n     },\n     \"fileId\": {\n      \"description\": \"ID of the attached file. Read-only.\\nFor Google Drive files, this is the ID of the corresponding Files resource entry in the Drive API.\",\n      \"type\": \"string\"\n     },\n     \"title\": {\n      \"description\": \"Attachment title.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"EventReminder\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"minutes\": {\n      \"description\": \"Number of minutes before the start of the event when the reminder should trigger. Valid values are between 0 and 40320 (4 weeks in minutes).\\nRequired when adding a reminder.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     },\n     \"method\": {\n      \"description\": \"The method used by this reminder. Possible values are:  \\n- \\\"email\\\" - Reminders are sent via email. \\n- \\\"popup\\\" - Reminders are sent via a UI popup.  \\nRequired when adding a reminder.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"EventWorkingLocationProperties\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"type\": {\n      \"description\": \"Type of the working location. Possible values are:  \\n- \\\"homeOffice\\\" - The user is working at home. \\n- \\\"officeLocation\\\" - The user is working from an office. \\n- \\\"customLocation\\\" - The user is working from a custom location.  Any details are specified in a sub-field of the specified name, but this field may be missing if empty. Any other fields are ignored.\\nRequired when adding working location properties.\",\n      \"type\": \"string\"\n     },\n     \"homeOffice\": {\n      \"description\": \"If present, specifies that the user is working at home.\"\n     },\n     \"customLocation\": {\n      \"description\": \"If present, specifies that the user is working from a custom location.\",\n      \"type\": \"object\",\n      \"properties\": {\n       \"label\": {\n        \"description\": \"An optional extra label for additional information.\",\n        \"type\": \"string\"\n       }\n      }\n     },\n     \"officeLocation\": {\n      \"description\": \"If present, specifies that the user is working from an office.\",\n      \"type\": \"object\",\n      \"properties\": {\n       \"buildingId\": {\n        \"description\": \"An optional building identifier. This should reference a building ID in the organization's Resources database.\",\n        \"type\": \"string\"\n       },\n       \"label\": {\n        \"description\": \"The office name that's displayed in Calendar Web and Mobile clients. We recommend you reference a building name in the organization's Resources database.\",\n        \"type\": \"string\"\n       },\n       \"floorSectionId\": {\n        \"description\": \"An optional floor section identifier.\",\n        \"type\": \"string\"\n       },\n       \"floorId\": {\n        \"description\": \"An optional floor identifier.\",\n        \"type\": \"string\"\n       },\n       \"deskId\": {\n        \"description\": \"An optional desk identifier.\",\n        \"type\": \"string\"\n       }\n      }\n     }\n    }\n   },\n   \"Setting\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"value\": {\n      \"description\": \"Value of the user setting. The format of the value depends on the ID of the setting. It must always be a UTF-8 string of length up to 1024 characters.\",\n      \"type\": \"string\"\n     },\n     \"kind\": {\n      \"description\": \"Type of the resource (\\\"calendar#setting\\\").\",\n      \"type\": \"string\"\n     },\n     \"id\": {\n      \"description\": \"The id of the user setting.\",\n      \"type\": \"string\"\n     },\n     \"etag\": {\n      \"description\": \"ETag of the resource.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"EventBirthdayProperties\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"type\": {\n      \"description\": \"Type of birthday or special event. Possible values are:  \\n- \\\"anniversary\\\" - An anniversary other than birthday. Always has a contact. \\n- \\\"birthday\\\" - A birthday event. This is the default value. \\n- \\\"custom\\\" - A special date whose label is further specified in the customTypeName field. Always has a contact. \\n- \\\"other\\\" - A special date which does not fall into the other categories, and does not have a custom label. Always has a contact. \\n- \\\"self\\\" - Calendar owner's own birthday. Cannot have a contact.  The Calendar API only supports creating events with the type \\\"birthday\\\". The type cannot be changed after the event is created.\",\n      \"type\": \"string\"\n     },\n     \"contact\": {\n      \"description\": \"Resource name of the contact this birthday event is linked to. This can be used to fetch contact details from People API. Format: \\\"people/c12345\\\". Read-only.\",\n      \"type\": \"string\"\n     },\n     \"customTypeName\": {\n      \"description\": \"Custom type label specified for this event. This is populated if birthdayProperties.type is set to \\\"custom\\\". Read-only.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"EntryPoint\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"passcode\": {\n      \"description\": \"The passcode to access the conference. The maximum length is 128 characters.\\nWhen creating new conference data, populate only the subset of {meetingCode, accessCode, passcode, password, pin} fields that match the terminology that the conference provider uses. Only the populated fields should be displayed.\",\n      \"type\": \"string\"\n     },\n     \"regionCode\": {\n      \"description\": \"The CLDR/ISO 3166 region code for the country associated with this phone access. Example: \\\"SE\\\" for Sweden.\\nCalendar backend will populate this field only for EntryPointType.PHONE.\",\n      \"type\": \"string\"\n     },\n     \"password\": {\n      \"description\": \"The password to access the conference. The maximum length is 128 characters.\\nWhen creating new conference data, populate only the subset of {meetingCode, accessCode, passcode, password, pin} fields that match the terminology that the conference provider uses. Only the populated fields should be displayed.\\nOptional.\",\n      \"type\": \"string\"\n     },\n     \"accessCode\": {\n      \"description\": \"The access code to access the conference. The maximum length is 128 characters.\\nWhen creating new conference data, populate only the subset of {meetingCode, accessCode, passcode, password, pin} fields that match the terminology that the conference provider uses. Only the populated fields should be displayed.\\nOptional.\",\n      \"type\": \"string\"\n     },\n     \"pin\": {\n      \"description\": \"The PIN to access the conference. The maximum length is 128 characters.\\nWhen creating new conference data, populate only the subset of {meetingCode, accessCode, passcode, password, pin} fields that match the terminology that the conference provider uses. Only the populated fields should be displayed.\\nOptional.\",\n      \"type\": \"string\"\n     },\n     \"entryPointFeatures\": {\n      \"description\": \"Features of the entry point, such as being toll or toll-free. One entry point can have multiple features. However, toll and toll-free cannot be both set on the same entry point.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"label\": {\n      \"description\": \"The label for the URI. Visible to end users. Not localized. The maximum length is 512 characters.\\nExamples:  \\n- for video: meet.google.com/aaa-bbbb-ccc\\n- for phone: +1 123 268 2601\\n- for sip: 12345678@altostrat.com\\n- for more: should not be filled  \\nOptional.\",\n      \"type\": \"string\"\n     },\n     \"uri\": {\n      \"description\": \"The URI of the entry point. The maximum length is 1300 characters.\\nFormat:  \\n- for video, http: or https: schema is required.\\n- for phone, tel: schema is required. The URI should include the entire dial sequence (e.g., tel:+12345678900,,,123456789;1234).\\n- for sip, sip: schema is required, e.g., sip:12345678@myprovider.com.\\n- for more, http: or https: schema is required.\",\n      \"type\": \"string\"\n     },\n     \"entryPointType\": {\n      \"description\": \"The type of the conference entry point.\\nPossible values are:  \\n- \\\"video\\\" - joining a conference over HTTP. A conference can have zero or one video entry point.\\n- \\\"phone\\\" - joining a conference by dialing a phone number. A conference can have zero or more phone entry points.\\n- \\\"sip\\\" - joining a conference over SIP. A conference can have zero or one sip entry point.\\n- \\\"more\\\" - further conference joining instructions, for example additional phone numbers. A conference can have zero or one more entry point. A conference with only a more entry point is not a valid conference.\",\n      \"type\": \"string\"\n     },\n     \"meetingCode\": {\n      \"description\": \"The meeting code to access the conference. The maximum length is 128 characters.\\nWhen creating new conference data, populate only the subset of {meetingCode, accessCode, passcode, password, pin} fields that match the terminology that the conference provider uses. Only the populated fields should be displayed.\\nOptional.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"AclRule\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"scope\": {\n      \"description\": \"The extent to which calendar access is granted by this ACL rule.\",\n      \"type\": \"object\",\n      \"properties\": {\n       \"type\": {\n        \"description\": \"The type of the scope. Possible values are:  \\n- \\\"default\\\" - The public scope. This is the default value. \\n- \\\"user\\\" - Limits the scope to a single user. \\n- \\\"group\\\" - Limits the scope to a group. \\n- \\\"domain\\\" - Limits the scope to a domain.  Note: The permissions granted to the \\\"default\\\", or public, scope apply to any user, authenticated or not.\",\n        \"type\": \"string\"\n       },\n       \"value\": {\n        \"description\": \"The email address of a user or group, or the name of a domain, depending on the scope type. Omitted for type \\\"default\\\".\",\n        \"type\": \"string\"\n       }\n      }\n     },\n     \"kind\": {\n      \"description\": \"Type of the resource (\\\"calendar#aclRule\\\").\",\n      \"type\": \"string\"\n     },\n     \"role\": {\n      \"description\": \"The role assigned to the scope. Possible values are:  \\n- \\\"none\\\" - Provides no access. \\n- \\\"freeBusyReader\\\" - Provides read access to free/busy information. \\n- \\\"reader\\\" - Provides read access to the calendar. Private events will appear to users with reader access, but event details will be hidden. \\n- \\\"writerWithoutPrivateAccess\\\" - Provides read and write access to the calendar. Private events will appear to users with writerWithoutPrivateAccess access, but event details will be hidden. \\n- \\\"writer\\\" - Provides read and write access to the calendar. Private events will appear to users with writer access, and event details will be visible. Provides read access to the calendar's ACLs. \\n- \\\"owner\\\" - Provides manager access to the calendar. This role has all of the permissions of the writer role with the additional ability to modify access levels of other users.\\nImportant: the owner role is different from the calendar's data owner. A calendar has a single data owner, but can have multiple users with owner role.\",\n      \"type\": \"string\"\n     },\n     \"etag\": {\n      \"description\": \"ETag of the resource.\",\n      \"type\": \"string\"\n     },\n     \"id\": {\n      \"description\": \"Identifier of the Access Control List (ACL) rule. See Sharing calendars.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"FreeBusyRequest\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"groupExpansionMax\": {\n      \"description\": \"Maximal number of calendar identifiers to be provided for a single group. Optional. An error is returned for a group with more members than this value. Maximum value is 100.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     },\n     \"calendarExpansionMax\": {\n      \"description\": \"Maximal number of calendars for which FreeBusy information is to be provided. Optional. Maximum value is 50.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     },\n     \"timeMax\": {\n      \"description\": \"The end of the interval for the query formatted as per RFC3339.\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     },\n     \"items\": {\n      \"description\": \"List of calendars and/or groups to query.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/FreeBusyRequestItem\"\n      }\n     },\n     \"timeMin\": {\n      \"description\": \"The start of the interval for the query formatted as per RFC3339.\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     },\n     \"timeZone\": {\n      \"description\": \"Time zone used in the response. Optional. The default is UTC.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"ConferenceData\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"signature\": {\n      \"description\": \"The signature of the conference data.\\nGenerated on server side.\\nUnset for a conference with a failed create request.\\nOptional for a conference with a pending create request.\",\n      \"type\": \"string\"\n     },\n     \"notes\": {\n      \"description\": \"Additional notes (such as instructions from the domain administrator, legal notices) to display to the user. Can contain HTML. The maximum length is 2048 characters. Optional.\",\n      \"type\": \"string\"\n     },\n     \"entryPoints\": {\n      \"description\": \"Information about individual conference entry points, such as URLs or phone numbers.\\nAll of them must belong to the same conference.\\nEither conferenceSolution and at least one entryPoint, or createRequest is required.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/EntryPoint\"\n      }\n     },\n     \"conferenceSolution\": {\n      \"$ref\": \"#/components/schemas/ConferenceSolution\"\n     },\n     \"conferenceId\": {\n      \"description\": \"The ID of the conference.\\nCan be used by developers to keep track of conferences, should not be displayed to users.\\nThe ID value is formed differently for each conference solution type:  \\n- eventHangout: ID is not set. (This conference type is deprecated.)\\n- eventNamedHangout: ID is the name of the Hangout. (This conference type is deprecated.)\\n- hangoutsMeet: ID is the 10-letter meeting code, for example aaa-bbbb-ccc.\\n- addOn: ID is defined by the third-party provider.  Optional.\",\n      \"type\": \"string\"\n     },\n     \"createRequest\": {\n      \"$ref\": \"#/components/schemas/CreateConferenceRequest\"\n     },\n     \"parameters\": {\n      \"$ref\": \"#/components/schemas/ConferenceParameters\"\n     }\n    }\n   },\n   \"FreeBusyCalendar\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"errors\": {\n      \"description\": \"Optional error(s) (if computation for the calendar failed).\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Error\"\n      }\n     },\n     \"busy\": {\n      \"description\": \"List of time ranges during which this calendar should be regarded as busy.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/TimePeriod\"\n      }\n     }\n    }\n   },\n   \"ConferenceProperties\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"allowedConferenceSolutionTypes\": {\n      \"description\": \"The types of conference solutions that are supported for this calendar.\\nThe possible values are:  \\n- \\\"eventHangout\\\" \\n- \\\"eventNamedHangout\\\" \\n- \\\"hangoutsMeet\\\"  Optional.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     }\n    }\n   },\n   \"Colors\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"updated\": {\n      \"description\": \"Last modification time of the color palette (as a RFC3339 timestamp). Read-only.\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     },\n     \"calendar\": {\n      \"description\": \"A global palette of calendar colors, mapping from the color ID to its definition. A calendarListEntry resource refers to one of these color IDs in its colorId field. Read-only.\",\n      \"type\": \"object\",\n      \"additionalProperties\": {\n       \"$ref\": \"#/components/schemas/ColorDefinition\"\n      }\n     },\n     \"event\": {\n      \"description\": \"A global palette of event colors, mapping from the color ID to its definition. An event resource may refer to one of these color IDs in its colorId field. Read-only.\",\n      \"type\": \"object\",\n      \"additionalProperties\": {\n       \"$ref\": \"#/components/schemas/ColorDefinition\"\n      }\n     },\n     \"kind\": {\n      \"description\": \"Type of the resource (\\\"calendar#colors\\\").\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"TimePeriod\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"start\": {\n      \"description\": \"The (inclusive) start of the time period.\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     },\n     \"end\": {\n      \"description\": \"The (exclusive) end of the time period.\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     }\n    }\n   },\n   \"CalendarListEntry\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"foregroundColor\": {\n      \"description\": \"The foreground color of the calendar in the hexadecimal format \\\"#ffffff\\\". This property supersedes the index-based colorId property. To set or change this property, you need to specify colorRgbFormat=true in the parameters of the insert, update and patch methods. Optional.\",\n      \"type\": \"string\"\n     },\n     \"notificationSettings\": {\n      \"description\": \"The notifications that the authenticated user is receiving for this calendar.\",\n      \"type\": \"object\",\n      \"properties\": {\n       \"notifications\": {\n        \"description\": \"The list of notifications set for this calendar.\",\n        \"type\": \"array\",\n        \"items\": {\n         \"$ref\": \"#/components/schemas/CalendarNotification\"\n        }\n       }\n      }\n     },\n     \"accessRole\": {\n      \"description\": \"The effective access role that the authenticated user has on the calendar. Read-only. Possible values are:  \\n- \\\"freeBusyReader\\\" - Provides read access to free/busy information. \\n- \\\"reader\\\" - Provides read access to the calendar. Private events will appear to users with reader access, but event details will be hidden. \\n- \\\"writerWithoutPrivateAccess\\\" - Provides read and write access to the calendar. Private events will appear to users with writerWithoutPrivateAccess access, but event details will be hidden. \\n- \\\"writer\\\" - Provides read and write access to the calendar. Private events will appear to users with writer access, and event details will be visible. \\n- \\\"owner\\\" - Provides manager access to the calendar. This role has all of the permissions of the writer role with the additional ability to see and modify access levels of other users.\\nImportant: the owner role is different from the calendar's data owner. A calendar has a single data owner, but can have multiple users with owner role.\",\n      \"type\": \"string\"\n     },\n     \"summaryOverride\": {\n      \"description\": \"The summary that the authenticated user has set for this calendar. Optional.\",\n      \"type\": \"string\"\n     },\n     \"hidden\": {\n      \"description\": \"Whether the calendar has been hidden from the list. Optional. The attribute is only returned when the calendar is hidden, in which case the value is true.\",\n      \"type\": \"boolean\"\n     },\n     \"selected\": {\n      \"description\": \"Whether the calendar content shows up in the calendar UI. Optional. The default is False.\",\n      \"type\": \"boolean\"\n     },\n     \"conferenceProperties\": {\n      \"$ref\": \"#/components/schemas/ConferenceProperties\"\n     },\n     \"id\": {\n      \"description\": \"Identifier of the calendar.\",\n      \"type\": \"string\"\n     },\n     \"location\": {\n      \"description\": \"Geographic location of the calendar as free-form text. Optional. Read-only.\",\n      \"type\": \"string\"\n     },\n     \"defaultReminders\": {\n      \"description\": \"The default reminders that the authenticated user has for this calendar.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/EventReminder\"\n      }\n     },\n     \"etag\": {\n      \"description\": \"ETag of the resource.\",\n      \"type\": \"string\"\n     },\n     \"autoAcceptInvitations\": {\n      \"description\": \"Whether this calendar automatically accepts invitations. Only valid for resource calendars. Read-only.\",\n      \"type\": \"boolean\"\n     },\n     \"backgroundColor\": {\n      \"description\": \"The main color of the calendar in the hexadecimal format \\\"#0088aa\\\". This property supersedes the index-based colorId property. To set or change this property, you need to specify colorRgbFormat=true in the parameters of the insert, update and patch methods. Optional.\",\n      \"type\": \"string\"\n     },\n     \"dataOwner\": {\n      \"description\": \"The email of the owner of the calendar. Set only for secondary calendars. Read-only.\",\n      \"type\": \"string\"\n     },\n     \"kind\": {\n      \"description\": \"Type of the resource (\\\"calendar#calendarListEntry\\\").\",\n      \"type\": \"string\"\n     },\n     \"summary\": {\n      \"description\": \"Title of the calendar. Read-only.\",\n      \"type\": \"string\"\n     },\n     \"description\": {\n      \"description\": \"Description of the calendar. Optional. Read-only.\",\n      \"type\": \"string\"\n     },\n     \"deleted\": {\n      \"description\": \"Whether this calendar list entry has been deleted from the calendar list. Read-only. Optional. The default is False.\",\n      \"type\": \"boolean\"\n     },\n     \"colorId\": {\n      \"description\": \"The color of the calendar. This is an ID referring to an entry in the calendar section of the colors definition (see the colors endpoint). This property is superseded by the backgroundColor and foregroundColor properties and can be ignored when using these properties. Optional.\",\n      \"type\": \"string\"\n     },\n     \"primary\": {\n      \"description\": \"Whether the calendar is the primary calendar of the authenticated user. Read-only. Optional. The default is False.\",\n      \"type\": \"boolean\"\n     },\n     \"timeZone\": {\n      \"description\": \"The time zone of the calendar. Optional. Read-only.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"ConferenceSolution\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"name\": {\n      \"description\": \"The user-visible name of this solution. Not localized.\",\n      \"type\": \"string\"\n     },\n     \"key\": {\n      \"$ref\": \"#/components/schemas/ConferenceSolutionKey\"\n     },\n     \"iconUri\": {\n      \"description\": \"The user-visible icon for this solution.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"Events\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"updated\": {\n      \"description\": \"Last modification time of the calendar (as a RFC3339 timestamp). Read-only.\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     },\n     \"summary\": {\n      \"description\": \"Title of the calendar. Read-only.\",\n      \"type\": \"string\"\n     },\n     \"description\": {\n      \"description\": \"Description of the calendar. Read-only.\",\n      \"type\": \"string\"\n     },\n     \"defaultReminders\": {\n      \"description\": \"The default reminders on the calendar for the authenticated user. These reminders apply to all events on this calendar that do not explicitly override them (i.e. do not have reminders.useDefault set to True).\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/EventReminder\"\n      }\n     },\n     \"timeZone\": {\n      \"description\": \"The time zone of the calendar. Read-only.\",\n      \"type\": \"string\"\n     },\n     \"nextPageToken\": {\n      \"description\": \"Token used to access the next page of this result. Omitted if no further results are available, in which case nextSyncToken is provided.\",\n      \"type\": \"string\"\n     },\n     \"accessRole\": {\n      \"description\": \"The user's access role for this calendar. Read-only. Possible values are:  \\n- \\\"none\\\" - The user has no access. \\n- \\\"freeBusyReader\\\" - The user has read access to free/busy information. \\n- \\\"reader\\\" - The user has read access to the calendar. Private events will appear to users with reader access, but event details will be hidden. \\n- \\\"writerWithoutPrivateAccess\\\" - The user has read and write access to the calendar. Private events will appear to users with writerWithoutPrivateAccess access, but event details will be hidden. \\n- \\\"writer\\\" - The user has read and write access to the calendar. Private events will appear to users with writer access, and event details will be visible. \\n- \\\"owner\\\" - The user has manager access to the calendar. This role has all of the permissions of the writer role with the additional ability to see and modify access levels of other users.\\nImportant: the owner role is different from the calendar's data owner. A calendar has a single data owner, but can have multiple users with owner role.\",\n      \"type\": \"string\"\n     },\n     \"items\": {\n      \"description\": \"List of events on the calendar.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Event\"\n      }\n     },\n     \"etag\": {\n      \"description\": \"ETag of the collection.\",\n      \"type\": \"string\"\n     },\n     \"kind\": {\n      \"description\": \"Type of the collection (\\\"calendar#events\\\").\",\n      \"type\": \"string\"\n     },\n     \"nextSyncToken\": {\n      \"description\": \"Token used at a later point in time to retrieve only the entries that have changed since this result was returned. Omitted if further results are available, in which case nextPageToken is provided.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"CreateConferenceRequest\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"conferenceSolutionKey\": {\n      \"$ref\": \"#/components/schemas/ConferenceSolutionKey\"\n     },\n     \"requestId\": {\n      \"description\": \"The client-generated unique ID for this request.\\nClients should regenerate this ID for every new request. If an ID provided is the same as for the previous request, the request is ignored.\",\n      \"type\": \"string\"\n     },\n     \"status\": {\n      \"$ref\": \"#/components/schemas/ConferenceRequestStatus\"\n     }\n    }\n   },\n   \"Calendar\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"description\": {\n      \"description\": \"Description of the calendar. Optional.\",\n      \"type\": \"string\"\n     },\n     \"dataOwner\": {\n      \"description\": \"The email of the owner of the calendar. Set only for secondary calendars. Read-only.\",\n      \"type\": \"string\"\n     },\n     \"timeZone\": {\n      \"description\": \"The time zone of the calendar. (Formatted as an IANA Time Zone Database name, e.g. \\\"Europe/Zurich\\\".) Optional.\",\n      \"type\": \"string\"\n     },\n     \"id\": {\n      \"description\": \"Identifier of the calendar. To retrieve IDs call the calendarList.list() method.\",\n      \"type\": \"string\"\n     },\n     \"labelProperties\": {\n      \"$ref\": \"#/components/schemas/LabelProperties\"\n     },\n     \"autoAcceptInvitations\": {\n      \"description\": \"Whether this calendar automatically accepts invitations. Only valid for resource calendars.\",\n      \"type\": \"boolean\"\n     },\n     \"summary\": {\n      \"description\": \"Title of the calendar.\",\n      \"type\": \"string\"\n     },\n     \"kind\": {\n      \"description\": \"Type of the resource (\\\"calendar#calendar\\\").\",\n      \"type\": \"string\"\n     },\n     \"conferenceProperties\": {\n      \"$ref\": \"#/components/schemas/ConferenceProperties\"\n     },\n     \"location\": {\n      \"description\": \"Geographic location of the calendar as free-form text. Optional.\",\n      \"type\": \"string\"\n     },\n     \"etag\": {\n      \"description\": \"ETag of the resource.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"EventAttendee\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"resource\": {\n      \"description\": \"Whether the attendee is a resource. Can only be set when the attendee is added to the event for the first time. Subsequent modifications are ignored. Optional. The default is False.\",\n      \"type\": \"boolean\"\n     },\n     \"displayName\": {\n      \"description\": \"The attendee's name, if available. Optional.\",\n      \"type\": \"string\"\n     },\n     \"optional\": {\n      \"description\": \"Whether this is an optional attendee. Optional. The default is False.\",\n      \"type\": \"boolean\"\n     },\n     \"asyncOperation\": {\n      \"description\": \"If present, indicates the status of an asynchronous operation ongoing for this attendee (e.g. listing of members of large attendee groups). Read-only. The default is to not be present.\\nPossible values are:  \\n- \\\"inProgress\\\" - The asynchronous operation is in progress. \\n- (not present) - Otherwise.\",\n      \"type\": \"string\"\n     },\n     \"additionalGuests\": {\n      \"description\": \"Number of additional guests. Optional. The default is 0.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     },\n     \"organizer\": {\n      \"description\": \"Whether the attendee is the organizer of the event. Read-only. The default is False.\",\n      \"type\": \"boolean\"\n     },\n     \"responseStatus\": {\n      \"description\": \"The attendee's response status. Possible values are:  \\n- \\\"needsAction\\\" - The attendee has not responded to the invitation (recommended for new events). \\n- \\\"declined\\\" - The attendee has declined the invitation. \\n- \\\"tentative\\\" - The attendee has tentatively accepted the invitation. \\n- \\\"accepted\\\" - The attendee has accepted the invitation.  Warning: If you add an event using the values declined, tentative, or accepted, attendees with the \\\"Add invitations to my calendar\\\" setting set to \\\"When I respond to invitation in email\\\" or \\\"Only if the sender is known\\\" might have their response reset to needsAction and won't see an event in their calendar unless they change their response in the event invitation email. Furthermore, if more than 200 guests are invited to the event, response status is not propagated to the guests.\",\n      \"type\": \"string\"\n     },\n     \"id\": {\n      \"description\": \"The attendee's Profile ID, if available.\",\n      \"type\": \"string\"\n     },\n     \"email\": {\n      \"description\": \"The attendee's email address, if available. This field must be present when adding an attendee. It must be a valid email address as per RFC5322.\\nRequired when adding an attendee.\",\n      \"type\": \"string\"\n     },\n     \"comment\": {\n      \"description\": \"The attendee's response comment. Optional.\",\n      \"type\": \"string\"\n     },\n     \"self\": {\n      \"description\": \"Whether this entry represents the calendar on which this copy of the event appears. Read-only. The default is False.\",\n      \"type\": \"boolean\"\n     }\n    }\n   },\n   \"EventDateTime\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"dateTime\": {\n      \"description\": \"The time, as a combined date-time value (formatted according to RFC3339). A time zone offset is required unless a time zone is explicitly specified in timeZone.\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     },\n     \"date\": {\n      \"description\": \"The date, in the format \\\"yyyy-mm-dd\\\", if this is an all-day event.\",\n      \"type\": \"string\",\n      \"format\": \"date\"\n     },\n     \"timeZone\": {\n      \"description\": \"The time zone in which the time is specified. (Formatted as an IANA Time Zone Database name, e.g. \\\"Europe/Zurich\\\".) For recurring events this field is required and specifies the time zone in which the recurrence is expanded. For single events this field is optional and indicates a custom time zone for the event start/end.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"Acl\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"items\": {\n      \"description\": \"List of rules on the access control list.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/AclRule\"\n      }\n     },\n     \"kind\": {\n      \"description\": \"Type of the collection (\\\"calendar#acl\\\").\",\n      \"type\": \"string\"\n     },\n     \"nextSyncToken\": {\n      \"description\": \"Token used at a later point in time to retrieve only the entries that have changed since this result was returned. Omitted if further results are available, in which case nextPageToken is provided.\",\n      \"type\": \"string\"\n     },\n     \"nextPageToken\": {\n      \"description\": \"Token used to access the next page of this result. Omitted if no further results are available, in which case nextSyncToken is provided.\",\n      \"type\": \"string\"\n     },\n     \"etag\": {\n      \"description\": \"ETag of the collection.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"CalendarNotification\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"method\": {\n      \"description\": \"The method used to deliver the notification. The possible value is:  \\n- \\\"email\\\" - Notifications are sent via email.  \\nRequired when adding a notification.\",\n      \"type\": \"string\"\n     },\n     \"type\": {\n      \"description\": \"The type of notification. Possible values are:  \\n- \\\"eventCreation\\\" - Notification sent when a new event is put on the calendar. \\n- \\\"eventChange\\\" - Notification sent when an event is changed. \\n- \\\"eventCancellation\\\" - Notification sent when an event is cancelled. \\n- \\\"eventResponse\\\" - Notification sent when an attendee responds to the event invitation. \\n- \\\"agenda\\\" - An agenda with the events of the day (sent out in the morning).  \\nRequired when adding a notification.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"ConferenceParameters\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"addOnParameters\": {\n      \"$ref\": \"#/components/schemas/ConferenceParametersAddOnParameters\"\n     }\n    }\n   },\n   \"ConferenceParametersAddOnParameters\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"parameters\": {\n      \"type\": \"object\",\n      \"additionalProperties\": {\n       \"type\": \"string\"\n      }\n     }\n    }\n   },\n   \"CalendarList\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"etag\": {\n      \"description\": \"ETag of the collection.\",\n      \"type\": \"string\"\n     },\n     \"kind\": {\n      \"description\": \"Type of the collection (\\\"calendar#calendarList\\\").\",\n      \"type\": \"string\"\n     },\n     \"nextSyncToken\": {\n      \"description\": \"Token used at a later point in time to retrieve only the entries that have changed since this result was returned. Omitted if further results are available, in which case nextPageToken is provided.\",\n      \"type\": \"string\"\n     },\n     \"items\": {\n      \"description\": \"Calendars that are present on the user's calendar list.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/CalendarListEntry\"\n      }\n     },\n     \"nextPageToken\": {\n      \"description\": \"Token used to access the next page of this result. Omitted if no further results are available, in which case nextSyncToken is provided.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"Event\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"eventLabelId\": {\n      \"description\": \"The ID of the event label assigned to the event. Optional. This refers to the ID of an entry in the labelProperties.eventLabels property of the calendar (see the Calendars.get endpoint.)\\nThis property supersedes the index-based colorId property. To set or change this property, you need to specify eventLabelVersion=1 in the parameters of the insert, import, update, and patch methods.\\nSetting an empty string, or not setting this field at all, will remove the existing label from the event.\",\n      \"type\": \"string\"\n     },\n     \"etag\": {\n      \"description\": \"ETag of the resource.\",\n      \"type\": \"string\"\n     },\n     \"attachments\": {\n      \"description\": \"File attachments for the event.\\nIn order to modify attachments the supportsAttachments request parameter should be set to true.\\nThere can be at most 25 attachments per event,\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/EventAttachment\"\n      }\n     },\n     \"focusTimeProperties\": {\n      \"$ref\": \"#/components/schemas/EventFocusTimeProperties\"\n     },\n     \"gadget\": {\n      \"description\": \"A gadget that extends this event. Gadgets are deprecated; this structure is instead only used for returning birthday calendar metadata.\",\n      \"type\": \"object\",\n      \"properties\": {\n       \"type\": {\n        \"description\": \"The gadget's type. Deprecated.\",\n        \"type\": \"string\"\n       },\n       \"preferences\": {\n        \"description\": \"Preferences.\",\n        \"type\": \"object\",\n        \"additionalProperties\": {\n         \"description\": \"The preference name and corresponding value.\",\n         \"type\": \"string\"\n        }\n       },\n       \"title\": {\n        \"description\": \"The gadget's title. Deprecated.\",\n        \"type\": \"string\"\n       },\n       \"width\": {\n        \"description\": \"The gadget's width in pixels. The width must be an integer greater than 0. Optional. Deprecated.\",\n        \"type\": \"integer\",\n        \"format\": \"int32\"\n       },\n       \"height\": {\n        \"description\": \"The gadget's height in pixels. The height must be an integer greater than 0. Optional. Deprecated.\",\n        \"type\": \"integer\",\n        \"format\": \"int32\"\n       },\n       \"display\": {\n        \"description\": \"The gadget's display mode. Deprecated. Possible values are:  \\n- \\\"icon\\\" - The gadget displays next to the event's title in the calendar view. \\n- \\\"chip\\\" - The gadget displays when the event is clicked.\",\n        \"type\": \"string\"\n       },\n       \"iconLink\": {\n        \"description\": \"The gadget's icon URL. The URL scheme must be HTTPS. Deprecated.\",\n        \"type\": \"string\"\n       },\n       \"link\": {\n        \"description\": \"The gadget's URL. The URL scheme must be HTTPS. Deprecated.\",\n        \"type\": \"string\"\n       }\n      }\n     },\n     \"guestsCanSeeOtherGuests\": {\n      \"description\": \"Whether attendees other than the organizer can see who the event's attendees are. Optional. The default is True.\",\n      \"type\": \"boolean\"\n     },\n     \"start\": {\n      \"$ref\": \"#/components/schemas/EventDateTime\"\n     },\n     \"summary\": {\n      \"description\": \"Title of the event.\",\n      \"type\": \"string\"\n     },\n     \"sequence\": {\n      \"description\": \"Sequence number as per iCalendar.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     },\n     \"iCalUID\": {\n      \"description\": \"Event unique identifier as defined in RFC5545. It is used to uniquely identify events accross calendaring systems and must be supplied when importing events via the import method.\\nNote that the iCalUID and the id are not identical and only one of them should be supplied at event creation time. One difference in their semantics is that in recurring events, all occurrences of one event have different ids while they all share the same iCalUIDs. To retrieve an event using its iCalUID, call the events.list method using the iCalUID parameter. To retrieve an event using its id, call the events.get method.\",\n      \"type\": \"string\"\n     },\n     \"organizer\": {\n      \"description\": \"The organizer of the event. If the organizer is also an attendee, this is indicated with a separate entry in attendees with the organizer field set to True. To change the organizer, use the move operation. Read-only, except when importing an event.\",\n      \"type\": \"object\",\n      \"properties\": {\n       \"self\": {\n        \"description\": \"Whether the organizer corresponds to the calendar on which this copy of the event appears. Read-only. The default is False.\",\n        \"type\": \"boolean\"\n       },\n       \"email\": {\n        \"description\": \"The organizer's email address, if available. It must be a valid email address as per RFC5322.\",\n        \"type\": \"string\"\n       },\n       \"displayName\": {\n        \"description\": \"The organizer's name, if available.\",\n        \"type\": \"string\"\n       },\n       \"id\": {\n        \"description\": \"The organizer's Profile ID, if available.\",\n        \"type\": \"string\"\n       }\n      }\n     },\n     \"extendedProperties\": {\n      \"description\": \"Extended properties of the event.\",\n      \"type\": \"object\",\n      \"properties\": {\n       \"shared\": {\n        \"description\": \"Properties that are shared between copies of the event on other attendees' calendars.\",\n        \"type\": \"object\",\n        \"additionalProperties\": {\n         \"description\": \"The name of the shared property and the corresponding value.\",\n         \"type\": \"string\"\n        }\n       },\n       \"private\": {\n        \"description\": \"Properties that are private to the copy of the event that appears on this calendar.\",\n        \"type\": \"object\",\n        \"additionalProperties\": {\n         \"description\": \"The name of the private property and the corresponding value.\",\n         \"type\": \"string\"\n        }\n       }\n      }\n     },\n     \"transparency\": {\n      \"description\": \"Whether the event blocks time on the calendar. Optional. Possible values are:  \\n- \\\"opaque\\\" - Default value. The event does block time on the calendar. This is equivalent to setting Show me as to Busy in the Calendar UI. \\n- \\\"transparent\\\" - The event does not block time on the calendar. This is equivalent to setting Show me as to Available in the Calendar UI.\",\n      \"type\": \"string\"\n     },\n     \"workingLocationProperties\": {\n      \"$ref\": \"#/components/schemas/EventWorkingLocationProperties\"\n     },\n     \"conferenceData\": {\n      \"$ref\": \"#/components/schemas/ConferenceData\"\n     },\n     \"reminders\": {\n      \"description\": \"Information about the event's reminders for the authenticated user. Note that changing reminders does not also change the updated property of the enclosing event.\",\n      \"type\": \"object\",\n      \"properties\": {\n       \"useDefault\": {\n        \"description\": \"Whether the default reminders of the calendar apply to the event.\",\n        \"type\": \"boolean\"\n       },\n       \"overrides\": {\n        \"description\": \"If the event doesn't use the default reminders, this lists the reminders specific to the event, or, if not set, indicates that no reminders are set for this event. The maximum number of override reminders is 5.\",\n        \"type\": \"array\",\n        \"items\": {\n         \"$ref\": \"#/components/schemas/EventReminder\"\n        }\n       }\n      }\n     },\n     \"outOfOfficeProperties\": {\n      \"$ref\": \"#/components/schemas/EventOutOfOfficeProperties\"\n     },\n     \"attendees\": {\n      \"description\": \"The attendees of the event. See the Events with attendees guide for more information on scheduling events with other calendar users. Service accounts need to use domain-wide delegation of authority to populate the attendee list.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/EventAttendee\"\n      }\n     },\n     \"hangoutLink\": {\n      \"description\": \"An absolute link to the Google Hangout associated with this event. Read-only.\",\n      \"type\": \"string\"\n     },\n     \"anyoneCanAddSelf\": {\n      \"description\": \"Whether anyone can invite themselves to the event (deprecated). Optional. The default is False.\",\n      \"type\": \"boolean\"\n     },\n     \"creator\": {\n      \"description\": \"The creator of the event. Read-only.\",\n      \"type\": \"object\",\n      \"properties\": {\n       \"id\": {\n        \"description\": \"The creator's Profile ID, if available.\",\n        \"type\": \"string\"\n       },\n       \"displayName\": {\n        \"description\": \"The creator's name, if available.\",\n        \"type\": \"string\"\n       },\n       \"self\": {\n        \"description\": \"Whether the creator corresponds to the calendar on which this copy of the event appears. Read-only. The default is False.\",\n        \"type\": \"boolean\"\n       },\n       \"email\": {\n        \"description\": \"The creator's email address, if available.\",\n        \"type\": \"string\"\n       }\n      }\n     },\n     \"end\": {\n      \"$ref\": \"#/components/schemas/EventDateTime\"\n     },\n     \"recurringEventId\": {\n      \"description\": \"For an instance of a recurring event, this is the id of the recurring event to which this instance belongs. Immutable.\",\n      \"type\": \"string\"\n     },\n     \"kind\": {\n      \"description\": \"Type of the resource (\\\"calendar#event\\\").\",\n      \"type\": \"string\"\n     },\n     \"description\": {\n      \"description\": \"Description of the event. Can contain HTML. Optional.\",\n      \"type\": \"string\"\n     },\n     \"recurrence\": {\n      \"description\": \"List of RRULE, EXRULE, RDATE and EXDATE lines for a recurring event, as specified in RFC5545. Note that DTSTART and DTEND lines are not allowed in this field; event start and end times are specified in the start and end fields. This field is omitted for single events or instances of recurring events.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"birthdayProperties\": {\n      \"$ref\": \"#/components/schemas/EventBirthdayProperties\"\n     },\n     \"colorId\": {\n      \"description\": \"The color of the event. This is an ID referring to an entry in the event section of the colors definition (see the  colors endpoint). Optional.\",\n      \"type\": \"string\"\n     },\n     \"endTimeUnspecified\": {\n      \"description\": \"Whether the end time is actually unspecified. An end time is still provided for compatibility reasons, even if this attribute is set to True. The default is False.\",\n      \"type\": \"boolean\"\n     },\n     \"status\": {\n      \"description\": \"Status of the event. Optional. Possible values are:  \\n- \\\"confirmed\\\" - The event is confirmed. This is the default status. \\n- \\\"tentative\\\" - The event is tentatively confirmed. \\n- \\\"cancelled\\\" - The event is cancelled (deleted). The list method returns cancelled events only on incremental sync (when syncToken or updatedMin are specified) or if the showDeleted flag is set to true. The get method always returns them.\\nA cancelled status represents two different states depending on the event type:  \\n- Cancelled exceptions of an uncancelled recurring event indicate that this instance should no longer be presented to the user. Clients should store these events for the lifetime of the parent recurring event.\\nCancelled exceptions are only guaranteed to have values for the id, recurringEventId and originalStartTime fields populated. The other fields might be empty.  \\n- All other cancelled events represent deleted events. Clients should remove their locally synced copies. Such cancelled events will eventually disappear, so do not rely on them being available indefinitely.\\nDeleted events are only guaranteed to have the id field populated.   On the organizer's calendar, cancelled events continue to expose event details (summary, location, etc.) so that they can be restored (undeleted). Similarly, the events to which the user was invited and that they manually removed continue to provide details. However, incremental sync requests with showDeleted set to false will not return these details.\\nIf an event changes its organizer (for example via the move operation) and the original organizer is not on the attendee list, it will leave behind a cancelled event where only the id field is guaranteed to be populated.\",\n      \"type\": \"string\"\n     },\n     \"location\": {\n      \"description\": \"Geographic location of the event as free-form text. Optional.\",\n      \"type\": \"string\"\n     },\n     \"guestsCanModify\": {\n      \"description\": \"Whether attendees other than the organizer can modify the event. Optional. The default is False.\",\n      \"type\": \"boolean\"\n     },\n     \"originalStartTime\": {\n      \"$ref\": \"#/components/schemas/EventDateTime\"\n     },\n     \"attendeesOmitted\": {\n      \"description\": \"Whether attendees may have been omitted from the event's representation. When retrieving an event, this may be due to a restriction specified by the maxAttendee query parameter. When updating an event, this can be used to only update the participant's response. Optional. The default is False.\",\n      \"type\": \"boolean\"\n     },\n     \"guestsCanInviteOthers\": {\n      \"description\": \"Whether attendees other than the organizer can invite others to the event. Optional. The default is True.\",\n      \"type\": \"boolean\"\n     },\n     \"eventType\": {\n      \"description\": \"Specific type of the event. This cannot be modified after the event is created. Possible values are:  \\n- \\\"birthday\\\" - A special all-day event with an annual recurrence. \\n- \\\"default\\\" - A regular event or not further specified. \\n- \\\"focusTime\\\" - A focus-time event. \\n- \\\"fromGmail\\\" - An event from Gmail. This type of event cannot be created. \\n- \\\"outOfOffice\\\" - An out-of-office event. \\n- \\\"workingLocation\\\" - A working location event.\",\n      \"type\": \"string\"\n     },\n     \"created\": {\n      \"description\": \"Creation time of the event (as a RFC3339 timestamp). Read-only.\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     },\n     \"privateCopy\": {\n      \"description\": \"If set to True, Event propagation is disabled. Note that it is not the same thing as Private event properties. Optional. Immutable. The default is False.\",\n      \"type\": \"boolean\"\n     },\n     \"visibility\": {\n      \"description\": \"Visibility of the event. Optional. Possible values are:  \\n- \\\"default\\\" - Uses the default visibility for events on the calendar. This is the default value. \\n- \\\"public\\\" - The event is public and event details are visible to all readers of the calendar. \\n- \\\"private\\\" - The event is private and only event attendees may view event details. \\n- \\\"confidential\\\" - The event is private. This value is provided for compatibility reasons.  \\nNote on recurring events: Changing the visibility of a single instance of a recurring event can affect all instances of the series. If the new setting is more restrictive (e.g. from public to private), it is applied to all instances. If the new setting is less restrictive (e.g. from private to public), the change is ignored. To make a recurring event less restrictive, you must update the parent recurring event.\",\n      \"type\": \"string\"\n     },\n     \"id\": {\n      \"description\": \"Opaque identifier of the event. When creating new single or recurring events, you can specify their IDs. Provided IDs must follow these rules:  \\n- characters allowed in the ID are those used in base32hex encoding, i.e. lowercase letters a-v and digits 0-9, see section 3.1.2 in RFC2938 \\n- the length of the ID must be between 5 and 1024 characters \\n- the ID must be unique per calendar  Due to the globally distributed nature of the system, we cannot guarantee that ID collisions will be detected at event creation time. To minimize the risk of collisions we recommend using an established UUID algorithm such as one described in RFC4122.\\nIf you do not specify an ID, it will be automatically generated by the server.\\nNote that the icalUID and the id are not identical and only one of them should be supplied at event creation time. One difference in their semantics is that in recurring events, all occurrences of one event have different ids while they all share the same icalUIDs.\",\n      \"type\": \"string\"\n     },\n     \"source\": {\n      \"description\": \"Source from which the event was created. For example, a web page, an email message or any document identifiable by an URL with HTTP or HTTPS scheme. Can only be seen or modified by the creator of the event.\",\n      \"type\": \"object\",\n      \"properties\": {\n       \"url\": {\n        \"description\": \"URL of the source pointing to a resource. The URL scheme must be HTTP or HTTPS.\",\n        \"type\": \"string\"\n       },\n       \"title\": {\n        \"description\": \"Title of the source; for example a title of a web page or an email subject.\",\n        \"type\": \"string\"\n       }\n      }\n     },\n     \"locked\": {\n      \"description\": \"Whether this is a locked event copy where no changes can be made to the main event fields \\\"summary\\\", \\\"description\\\", \\\"location\\\", \\\"start\\\", \\\"end\\\" or \\\"recurrence\\\". The default is False. Read-Only.\",\n      \"type\": \"boolean\"\n     },\n     \"updated\": {\n      \"description\": \"Last modification time of the main event data (as a RFC3339 timestamp). Updating event reminders will not cause this to change. Read-only.\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     },\n     \"htmlLink\": {\n      \"description\": \"An absolute link to this event in the Google Calendar Web UI. Read-only.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"FreeBusyResponse\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"calendars\": {\n      \"description\": \"List of free/busy information for calendars.\",\n      \"type\": \"object\",\n      \"additionalProperties\": {\n       \"$ref\": \"#/components/schemas/FreeBusyCalendar\"\n      }\n     },\n     \"kind\": {\n      \"description\": \"Type of the resource (\\\"calendar#freeBusy\\\").\",\n      \"type\": \"string\"\n     },\n     \"timeMin\": {\n      \"description\": \"The start of the interval.\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     },\n     \"groups\": {\n      \"description\": \"Expansion of groups.\",\n      \"type\": \"object\",\n      \"additionalProperties\": {\n       \"$ref\": \"#/components/schemas/FreeBusyGroup\"\n      }\n     },\n     \"timeMax\": {\n      \"description\": \"The end of the interval.\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     }\n    }\n   },\n   \"EventFocusTimeProperties\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"chatStatus\": {\n      \"description\": \"The status to mark the user in Chat and related products. This can be available or doNotDisturb.\",\n      \"type\": \"string\"\n     },\n     \"declineMessage\": {\n      \"description\": \"Response message to set if an existing event or new invitation is automatically declined by Calendar.\",\n      \"type\": \"string\"\n     },\n     \"autoDeclineMode\": {\n      \"description\": \"Whether to decline meeting invitations which overlap Focus Time events. Valid values are declineNone, meaning that no meeting invitations are declined; declineAllConflictingInvitations, meaning that all conflicting meeting invitations that conflict with the event are declined; and declineOnlyNewConflictingInvitations, meaning that only new conflicting meeting invitations which arrive while the Focus Time event is present are to be declined.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"ConferenceRequestStatus\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"statusCode\": {\n      \"description\": \"The current status of the conference create request. Read-only.\\nThe possible values are:  \\n- \\\"pending\\\": the conference create request is still being processed.\\n- \\\"success\\\": the conference create request succeeded, the entry points are populated.\\n- \\\"failure\\\": the conference create request failed, there are no entry points.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"FreeBusyGroup\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"calendars\": {\n      \"description\": \"List of calendars' identifiers within a group.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"errors\": {\n      \"description\": \"Optional error(s) (if computation for the group failed).\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Error\"\n      }\n     }\n    }\n   },\n   \"ColorDefinition\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"background\": {\n      \"description\": \"The background color associated with this color definition.\",\n      \"type\": \"string\"\n     },\n     \"foreground\": {\n      \"description\": \"The foreground color that can be used to write on top of a background with 'background' color.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"FreeBusyRequestItem\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"id\": {\n      \"description\": \"The identifier of a calendar or a group.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"LabelProperties\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"eventLabels\": {\n      \"description\": \"Event labels defined on this calendar. If this is present when updating the calendar, it will replace the existing event labels.\\nExtend the list to add a new event label, and remove entities from the list to delete a label from calendar.\\nEach calendar can have a maximum of 200 labels.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/EventLabel\"\n      }\n     }\n    }\n   },\n   \"ConferenceSolutionKey\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"type\": {\n      \"description\": \"The conference solution type.\\nIf a client encounters an unfamiliar or empty type, it should still be able to display the entry points. However, it should disallow modifications.\\nThe possible values are:  \\n- \\\"eventHangout\\\" for Hangouts for consumers (deprecated; existing events may show this conference solution type but new conferences cannot be created)\\n- \\\"eventNamedHangout\\\" for classic Hangouts for Google Workspace users (deprecated; existing events may show this conference solution type but new conferences cannot be created)\\n- \\\"hangoutsMeet\\\" for Google Meet (http://meet.google.com)\\n- \\\"addOn\\\" for 3P conference providers\",\n      \"type\": \"string\"\n     }\n    }\n   }\n  },\n  \"securitySchemes\": {\n   \"bearer\": {\n    \"type\": \"http\",\n    \"scheme\": \"bearer\"\n   }\n  }\n }\n}\n"},{"path":"products/calendar/openapi.ts","content":"// Generated by scripts/google-vendor.ts from packages/google-calendar; edit the original and rerun it.\n// calendar-openapi.json is generated from Google's own Calendar v3 Discovery document (revision\n// 20261005) by packages/google-drive/discovery-to-openapi.mjs; see README. Credentials go only to\n// www.googleapis.com.\nimport type { JsonObject } from \"apps\";\nimport type { OpenapiToolNamesOptions } from \"apps/openapi\";\nimport calendar from \"./calendar-openapi.json\" with { type: \"json\" };\n\n// The inferred JSON type has no index signature, so widen it once here.\nconst document: JsonObject = JSON.parse(JSON.stringify(calendar));\n\n// Every operation in the generated document already carries a plain bearer requirement.\nexport const options = {\n  source: { document },\n  allowedOrigin: \"https://www.googleapis.com\",\n  securitySchemes: { bearer: { type: \"http\", scheme: \"bearer\" } },\n  methods: {\n    oauth: [{ scheme: \"bearer\", field: \"access_token\", part: \"value\", prefix: \"\" }],\n  },\n  oauth: [],\n} satisfies OpenapiToolNamesOptions;\n"},{"path":"products/contacts/openapi.json","content":"{\n \"openapi\": \"3.0.3\",\n \"info\": {\n  \"title\": \"People API\",\n  \"version\": \"v1 (discovery revision 20261007)\",\n  \"description\": \"Provides access to information about profiles and contacts.\"\n },\n \"servers\": [\n  {\n   \"url\": \"https://people.googleapis.com\"\n  }\n ],\n \"security\": [\n  {\n   \"bearer\": []\n  }\n ],\n \"paths\": {\n  \"/v1/people/{peopleId}:deleteContact\": {\n   \"delete\": {\n    \"operationId\": \"people.people.deleteContact\",\n    \"description\": \"Delete a contact person. Any non-contact data will not be deleted. Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.\",\n    \"parameters\": [\n     {\n      \"name\": \"peopleId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Identifier segment peopleId of the resource name.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Empty\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/v1/people:createContact\": {\n   \"post\": {\n    \"operationId\": \"people.people.createContact\",\n    \"description\": \"Create a new contact and return the person resource for that contact. The request returns a 400 error if more than one field is specified on a field that is a singleton for contact sources: * biographies * birthdays * genders * names Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.\",\n    \"parameters\": [\n     {\n      \"name\": \"sources\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. A mask of what source types to return. Defaults to READ_SOURCE_TYPE_CONTACT and READ_SOURCE_TYPE_PROFILE if not set.\",\n      \"schema\": {\n       \"type\": \"array\",\n       \"items\": {\n        \"type\": \"string\",\n        \"enum\": [\n         \"READ_SOURCE_TYPE_UNSPECIFIED\",\n         \"READ_SOURCE_TYPE_PROFILE\",\n         \"READ_SOURCE_TYPE_CONTACT\",\n         \"READ_SOURCE_TYPE_DOMAIN_CONTACT\",\n         \"READ_SOURCE_TYPE_OTHER_CONTACT\"\n        ]\n       }\n      }\n     },\n     {\n      \"name\": \"personFields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Required. A field mask to restrict which fields on each person are returned. Multiple fields can be specified by separating them with commas. Defaults to all fields if not set. Valid values are: * addresses * ageRanges * biographies * birthdays * calendarUrls * clientData * coverPhotos * emailAddresses * events * externalIds * genders * imClients * interests * locales * locations * memberships * metadata * miscKeywords * names * nicknames * occupations * organizations * phoneNumbers * photos * relations * sipAddresses * skills * urls * userDefined\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"google-fieldmask\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Person\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Person\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/v1/people/{peopleId}:updateContact\": {\n   \"patch\": {\n    \"operationId\": \"people.people.updateContact\",\n    \"description\": \"Update contact data for an existing contact person. Any non-contact data will not be modified. Any non-contact data in the person to update will be ignored. All fields specified in the `update_mask` will be replaced. The server returns a 400 error if `person.metadata.sources` is not specified for the contact to be updated or if there is no contact source. The server returns a 400 error with reason `\\\"failedPrecondition\\\"` if `person.metadata.sources.etag` is different than the contact's etag, which indicates the contact has changed since its data was read. Clients should get the latest person and merge their updates into the latest person. If making sequential updates to the same person, the etag from the `updateContact` response should be used to avoid failures. The server returns a 400 error if `memberships` are being updated and there are no contact group memberships specified on the person. The server returns a 400 error if more than one field is specified on a field that is a singleton for contact sources: * biographies * birthdays * genders * names Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.\",\n    \"parameters\": [\n     {\n      \"name\": \"updatePersonFields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Required. A field mask to restrict which fields on the person are updated. Multiple fields can be specified by separating them with commas. All updated fields will be replaced. Valid values are: * addresses * biographies * birthdays * calendarUrls * clientData * emailAddresses * events * externalIds * genders * imClients * interests * locales * locations * memberships * miscKeywords * names * nicknames * occupations * organizations * phoneNumbers * relations * sipAddresses * urls * userDefined\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"google-fieldmask\"\n      }\n     },\n     {\n      \"name\": \"sources\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. A mask of what source types to return. Defaults to READ_SOURCE_TYPE_CONTACT and READ_SOURCE_TYPE_PROFILE if not set.\",\n      \"schema\": {\n       \"type\": \"array\",\n       \"items\": {\n        \"type\": \"string\",\n        \"enum\": [\n         \"READ_SOURCE_TYPE_UNSPECIFIED\",\n         \"READ_SOURCE_TYPE_PROFILE\",\n         \"READ_SOURCE_TYPE_CONTACT\",\n         \"READ_SOURCE_TYPE_DOMAIN_CONTACT\",\n         \"READ_SOURCE_TYPE_OTHER_CONTACT\"\n        ]\n       }\n      }\n     },\n     {\n      \"name\": \"personFields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. A field mask to restrict which fields on each person are returned. Multiple fields can be specified by separating them with commas. Defaults to all fields if not set. Valid values are: * addresses * ageRanges * biographies * birthdays * calendarUrls * clientData * coverPhotos * emailAddresses * events * externalIds * genders * imClients * interests * locales * locations * memberships * metadata * miscKeywords * names * nicknames * occupations * organizations * phoneNumbers * photos * relations * sipAddresses * skills * urls * userDefined\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"google-fieldmask\"\n      }\n     },\n     {\n      \"name\": \"peopleId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Identifier segment peopleId of the resource name.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Person\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Person\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/v1/people/{peopleId}\": {\n   \"get\": {\n    \"operationId\": \"people.people.get\",\n    \"description\": \"Provides information about a person by specifying a resource name. Use `people/me` to indicate the authenticated user. The request returns a 400 error if 'personFields' is not specified.\",\n    \"parameters\": [\n     {\n      \"name\": \"requestMask.includeField\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Required. Comma-separated list of person fields to be included in the response. Each path should start with `person.`: for example, `person.names` or `person.photos`.\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"google-fieldmask\"\n      }\n     },\n     {\n      \"name\": \"sources\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. A mask of what source types to return. Defaults to READ_SOURCE_TYPE_PROFILE and READ_SOURCE_TYPE_CONTACT if not set.\",\n      \"schema\": {\n       \"type\": \"array\",\n       \"items\": {\n        \"type\": \"string\",\n        \"enum\": [\n         \"READ_SOURCE_TYPE_UNSPECIFIED\",\n         \"READ_SOURCE_TYPE_PROFILE\",\n         \"READ_SOURCE_TYPE_CONTACT\",\n         \"READ_SOURCE_TYPE_DOMAIN_CONTACT\",\n         \"READ_SOURCE_TYPE_OTHER_CONTACT\"\n        ]\n       }\n      }\n     },\n     {\n      \"name\": \"personFields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Required. A field mask to restrict which fields on the person are returned. Multiple fields can be specified by separating them with commas. Valid values are: * addresses * ageRanges * biographies * birthdays * calendarUrls * clientData * coverPhotos * emailAddresses * events * externalIds * genders * imClients * interests * locales * locations * memberships * metadata * miscKeywords * names * nicknames * occupations * organizations * phoneNumbers * photos * relations * sipAddresses * skills * urls * userDefined\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"google-fieldmask\"\n      }\n     },\n     {\n      \"name\": \"peopleId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Identifier segment peopleId of the resource name.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Person\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/v1/people/{peopleId}:updateContactPhoto\": {\n   \"patch\": {\n    \"operationId\": \"people.people.updateContactPhoto\",\n    \"description\": \"Update a contact's photo. Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.\",\n    \"parameters\": [\n     {\n      \"name\": \"peopleId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Identifier segment peopleId of the resource name.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/UpdateContactPhotoResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/UpdateContactPhotoRequest\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/v1/people:searchDirectoryPeople\": {\n   \"get\": {\n    \"operationId\": \"people.people.searchDirectoryPeople\",\n    \"description\": \"Provides a list of domain profiles and domain contacts in the authenticated user's domain directory that match the search query.\",\n    \"parameters\": [\n     {\n      \"name\": \"pageSize\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. The number of people to include in the response. Valid values are between 1 and 500, inclusive. Defaults to 100 if not set or set to 0.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. A page token, received from a previous response `next_page_token`. Provide this to retrieve the subsequent page. When paginating, all other parameters provided to `SearchDirectoryPeople` must match the first call that provided the page token.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"sources\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Required. Directory sources to return.\",\n      \"schema\": {\n       \"type\": \"array\",\n       \"items\": {\n        \"type\": \"string\",\n        \"enum\": [\n         \"DIRECTORY_SOURCE_TYPE_UNSPECIFIED\",\n         \"DIRECTORY_SOURCE_TYPE_DOMAIN_CONTACT\",\n         \"DIRECTORY_SOURCE_TYPE_DOMAIN_PROFILE\"\n        ]\n       }\n      }\n     },\n     {\n      \"name\": \"readMask\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Required. A field mask to restrict which fields on each person are returned. Multiple fields can be specified by separating them with commas. Valid values are: * addresses * ageRanges * biographies * birthdays * calendarUrls * clientData * coverPhotos * emailAddresses * events * externalIds * genders * imClients * interests * locales * locations * memberships * metadata * miscKeywords * names * nicknames * occupations * organizations * phoneNumbers * photos * relations * sipAddresses * skills * urls * userDefined\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"google-fieldmask\"\n      }\n     },\n     {\n      \"name\": \"query\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Required. Prefix query that matches fields in the person. Does NOT use the read_mask for determining what fields to match.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"mergeSources\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. Additional data to merge into the directory sources if they are connected through verified join keys such as email addresses or phone numbers.\",\n      \"schema\": {\n       \"type\": \"array\",\n       \"items\": {\n        \"type\": \"string\",\n        \"enum\": [\n         \"DIRECTORY_MERGE_SOURCE_TYPE_UNSPECIFIED\",\n         \"DIRECTORY_MERGE_SOURCE_TYPE_CONTACT\"\n        ]\n       }\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/SearchDirectoryPeopleResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/v1/people:listDirectoryPeople\": {\n   \"get\": {\n    \"operationId\": \"people.people.listDirectoryPeople\",\n    \"description\": \"Provides a list of domain profiles and domain contacts in the authenticated user's domain directory. When the `sync_token` is specified, resources deleted since the last sync will be returned as a person with `PersonMetadata.deleted` set to true. When the `page_token` or `sync_token` is specified, all other request parameters must match the first call. Writes may have a propagation delay of several minutes for sync requests. Incremental syncs are not intended for read-after-write use cases. See example usage at [List the directory people that have changed](/people/v1/directory#list_the_directory_people_that_have_changed).\",\n    \"parameters\": [\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. A page token, received from a previous response `next_page_token`. Provide this to retrieve the subsequent page. When paginating, all other parameters provided to `people.listDirectoryPeople` must match the first call that provided the page token.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"requestSyncToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. Whether the response should return `next_sync_token`. It can be used to get incremental changes since the last request by setting it on the request `sync_token`. More details about sync behavior at `people.listDirectoryPeople`.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"pageSize\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. The number of people to include in the response. Valid values are between 1 and 1000, inclusive. Defaults to 100 if not set or set to 0.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"syncToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. A sync token, received from a previous response `next_sync_token` Provide this to retrieve only the resources changed since the last request. When syncing, all other parameters provided to `people.listDirectoryPeople` must match the first call that provided the sync token. More details about sync behavior at `people.listDirectoryPeople`.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"mergeSources\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. Additional data to merge into the directory sources if they are connected through verified join keys such as email addresses or phone numbers.\",\n      \"schema\": {\n       \"type\": \"array\",\n       \"items\": {\n        \"type\": \"string\",\n        \"enum\": [\n         \"DIRECTORY_MERGE_SOURCE_TYPE_UNSPECIFIED\",\n         \"DIRECTORY_MERGE_SOURCE_TYPE_CONTACT\"\n        ]\n       }\n      }\n     },\n     {\n      \"name\": \"readMask\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Required. A field mask to restrict which fields on each person are returned. Multiple fields can be specified by separating them with commas. Valid values are: * addresses * ageRanges * biographies * birthdays * calendarUrls * clientData * coverPhotos * emailAddresses * events * externalIds * genders * imClients * interests * locales * locations * memberships * metadata * miscKeywords * names * nicknames * occupations * organizations * phoneNumbers * photos * relations * sipAddresses * skills * urls * userDefined\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"google-fieldmask\"\n      }\n     },\n     {\n      \"name\": \"sources\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Required. Directory sources to return.\",\n      \"schema\": {\n       \"type\": \"array\",\n       \"items\": {\n        \"type\": \"string\",\n        \"enum\": [\n         \"DIRECTORY_SOURCE_TYPE_UNSPECIFIED\",\n         \"DIRECTORY_SOURCE_TYPE_DOMAIN_CONTACT\",\n         \"DIRECTORY_SOURCE_TYPE_DOMAIN_PROFILE\"\n        ]\n       }\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/ListDirectoryPeopleResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/v1/people/{peopleId}:deleteContactPhoto\": {\n   \"delete\": {\n    \"operationId\": \"people.people.deleteContactPhoto\",\n    \"description\": \"Delete a contact's photo. Mutate requests for the same user should be done sequentially to avoid // lock contention.\",\n    \"parameters\": [\n     {\n      \"name\": \"sources\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. A mask of what source types to return. Defaults to READ_SOURCE_TYPE_CONTACT and READ_SOURCE_TYPE_PROFILE if not set.\",\n      \"schema\": {\n       \"type\": \"array\",\n       \"items\": {\n        \"type\": \"string\",\n        \"enum\": [\n         \"READ_SOURCE_TYPE_UNSPECIFIED\",\n         \"READ_SOURCE_TYPE_PROFILE\",\n         \"READ_SOURCE_TYPE_CONTACT\",\n         \"READ_SOURCE_TYPE_DOMAIN_CONTACT\",\n         \"READ_SOURCE_TYPE_OTHER_CONTACT\"\n        ]\n       }\n      }\n     },\n     {\n      \"name\": \"personFields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. A field mask to restrict which fields on the person are returned. Multiple fields can be specified by separating them with commas. Defaults to empty if not set, which will skip the post mutate get. Valid values are: * addresses * ageRanges * biographies * birthdays * calendarUrls * clientData * coverPhotos * emailAddresses * events * externalIds * genders * imClients * interests * locales * locations * memberships * metadata * miscKeywords * names * nicknames * occupations * organizations * phoneNumbers * photos * relations * sipAddresses * skills * urls * userDefined\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"google-fieldmask\"\n      }\n     },\n     {\n      \"name\": \"peopleId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Identifier segment peopleId of the resource name.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/DeleteContactPhotoResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/v1/people:batchCreateContacts\": {\n   \"post\": {\n    \"operationId\": \"people.people.batchCreateContacts\",\n    \"description\": \"Create a batch of new contacts and return the PersonResponses for the newly Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.\",\n    \"parameters\": [\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/BatchCreateContactsResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/BatchCreateContactsRequest\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/v1/people:batchUpdateContacts\": {\n   \"post\": {\n    \"operationId\": \"people.people.batchUpdateContacts\",\n    \"description\": \"Update a batch of contacts and return a map of resource names to PersonResponses for the updated contacts. Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.\",\n    \"parameters\": [\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/BatchUpdateContactsResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/BatchUpdateContactsRequest\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/v1/people:batchGet\": {\n   \"get\": {\n    \"operationId\": \"people.people.getBatchGet\",\n    \"description\": \"Provides information about a list of specific people by specifying a list of requested resource names. Use `people/me` to indicate the authenticated user. The request returns a 400 error if 'personFields' is not specified.\",\n    \"parameters\": [\n     {\n      \"name\": \"requestMask.includeField\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Required. Comma-separated list of person fields to be included in the response. Each path should start with `person.`: for example, `person.names` or `person.photos`.\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"google-fieldmask\"\n      }\n     },\n     {\n      \"name\": \"personFields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Required. A field mask to restrict which fields on each person are returned. Multiple fields can be specified by separating them with commas. Valid values are: * addresses * ageRanges * biographies * birthdays * calendarUrls * clientData * coverPhotos * emailAddresses * events * externalIds * genders * imClients * interests * locales * locations * memberships * metadata * miscKeywords * names * nicknames * occupations * organizations * phoneNumbers * photos * relations * sipAddresses * skills * urls * userDefined\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"google-fieldmask\"\n      }\n     },\n     {\n      \"name\": \"sources\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. A mask of what source types to return. Defaults to READ_SOURCE_TYPE_CONTACT and READ_SOURCE_TYPE_PROFILE if not set.\",\n      \"schema\": {\n       \"type\": \"array\",\n       \"items\": {\n        \"type\": \"string\",\n        \"enum\": [\n         \"READ_SOURCE_TYPE_UNSPECIFIED\",\n         \"READ_SOURCE_TYPE_PROFILE\",\n         \"READ_SOURCE_TYPE_CONTACT\",\n         \"READ_SOURCE_TYPE_DOMAIN_CONTACT\",\n         \"READ_SOURCE_TYPE_OTHER_CONTACT\"\n        ]\n       }\n      }\n     },\n     {\n      \"name\": \"resourceNames\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Required. The resource names of the people to provide information about. It's repeatable. The URL query parameter should be resourceNames=<name1>&resourceNames=<name2>&... - To get information about the authenticated user, specify `people/me`. - To get information about a google account, specify `people/{account_id}`. - To get information about a contact, specify the resource name that identifies the contact as returned by `people.connections.list`. There is a maximum of 200 resource names.\",\n      \"schema\": {\n       \"type\": \"array\",\n       \"items\": {\n        \"type\": \"string\"\n       }\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/GetPeopleResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/v1/people:searchContacts\": {\n   \"get\": {\n    \"operationId\": \"people.people.searchContacts\",\n    \"description\": \"Provides a list of contacts in the authenticated user's grouped contacts that matches the search query. The query matches on a contact's `names`, `nickNames`, `emailAddresses`, `phoneNumbers`, and `organizations` fields that are from the CONTACT source. **IMPORTANT**: Before searching, clients should send a warmup request with an empty query to update the cache. See https://developers.google.com/people/v1/contacts#search_the_users_contacts\",\n    \"parameters\": [\n     {\n      \"name\": \"pageSize\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. The number of results to return. Defaults to 10 if field is not set, or set to 0. Values greater than 30 will be capped to 30.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"readMask\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Required. A field mask to restrict which fields on each person are returned. Multiple fields can be specified by separating them with commas. Valid values are: * addresses * ageRanges * biographies * birthdays * calendarUrls * clientData * coverPhotos * emailAddresses * events * externalIds * genders * imClients * interests * locales * locations * memberships * metadata * miscKeywords * names * nicknames * occupations * organizations * phoneNumbers * photos * relations * sipAddresses * skills * urls * userDefined\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"google-fieldmask\"\n      }\n     },\n     {\n      \"name\": \"query\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Required. The plain-text query for the request. The query is used to match prefix phrases of the fields on a person. For example, a person with name \\\"foo name\\\" matches queries such as \\\"f\\\", \\\"fo\\\", \\\"foo\\\", \\\"foo n\\\", \\\"nam\\\", etc., but not \\\"oo n\\\".\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"sources\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. A mask of what source types to return. Defaults to READ_SOURCE_TYPE_CONTACT if not set.\",\n      \"schema\": {\n       \"type\": \"array\",\n       \"items\": {\n        \"type\": \"string\",\n        \"enum\": [\n         \"READ_SOURCE_TYPE_UNSPECIFIED\",\n         \"READ_SOURCE_TYPE_PROFILE\",\n         \"READ_SOURCE_TYPE_CONTACT\",\n         \"READ_SOURCE_TYPE_DOMAIN_CONTACT\",\n         \"READ_SOURCE_TYPE_OTHER_CONTACT\"\n        ]\n       }\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/SearchResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/v1/people:batchDeleteContacts\": {\n   \"post\": {\n    \"operationId\": \"people.people.batchDeleteContacts\",\n    \"description\": \"Delete a batch of contacts. Any non-contact data will not be deleted. Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.\",\n    \"parameters\": [\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Empty\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/BatchDeleteContactsRequest\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/v1/people/{peopleId}/connections\": {\n   \"get\": {\n    \"operationId\": \"people.people.connections.list\",\n    \"description\": \"Provides a list of the authenticated user's contacts. Sync tokens expire 7 days after the full sync. A request with an expired sync token will get an error with an [google.rpc.ErrorInfo](https://cloud.google.com/apis/design/errors#error_info) with reason \\\"EXPIRED_SYNC_TOKEN\\\". In the case of such an error clients should make a full sync request without a `sync_token`. The first page of a full sync request has an additional quota. If the quota is exceeded, a 429 error will be returned. This quota is fixed and can not be increased. When the `sync_token` is specified, resources deleted since the last sync will be returned as a person with `PersonMetadata.deleted` set to true. When the `page_token` or `sync_token` is specified, all other request parameters must match the first call. Writes may have a propagation delay of several minutes for sync requests. Incremental syncs are not intended for read-after-write use cases. See example usage at [List the user's contacts that have changed](/people/v1/contacts#list_the_users_contacts_that_have_changed).\",\n    \"parameters\": [\n     {\n      \"name\": \"pageSize\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. The number of connections to include in the response. Valid values are between 1 and 1000, inclusive. Defaults to 100 if not set or set to 0.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. A page token, received from a previous response `next_page_token`. Provide this to retrieve the subsequent page. When paginating, all other parameters provided to `people.connections.list` must match the first call that provided the page token.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"sources\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. A mask of what source types to return. Defaults to READ_SOURCE_TYPE_CONTACT and READ_SOURCE_TYPE_PROFILE if not set.\",\n      \"schema\": {\n       \"type\": \"array\",\n       \"items\": {\n        \"type\": \"string\",\n        \"enum\": [\n         \"READ_SOURCE_TYPE_UNSPECIFIED\",\n         \"READ_SOURCE_TYPE_PROFILE\",\n         \"READ_SOURCE_TYPE_CONTACT\",\n         \"READ_SOURCE_TYPE_DOMAIN_CONTACT\",\n         \"READ_SOURCE_TYPE_OTHER_CONTACT\"\n        ]\n       }\n      }\n     },\n     {\n      \"name\": \"syncToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. A sync token, received from a previous response `next_sync_token` Provide this to retrieve only the resources changed since the last request. When syncing, all other parameters provided to `people.connections.list` must match the first call that provided the sync token. More details about sync behavior at `people.connections.list`.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"requestMask.includeField\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Required. Comma-separated list of person fields to be included in the response. Each path should start with `person.`: for example, `person.names` or `person.photos`.\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"google-fieldmask\"\n      }\n     },\n     {\n      \"name\": \"requestSyncToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. Whether the response should return `next_sync_token` on the last page of results. It can be used to get incremental changes since the last request by setting it on the request `sync_token`. More details about sync behavior at `people.connections.list`.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"sortOrder\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. The order in which the connections should be sorted. Defaults to `LAST_MODIFIED_ASCENDING`.\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"enum\": [\n        \"LAST_MODIFIED_ASCENDING\",\n        \"LAST_MODIFIED_DESCENDING\",\n        \"FIRST_NAME_ASCENDING\",\n        \"LAST_NAME_ASCENDING\"\n       ]\n      }\n     },\n     {\n      \"name\": \"personFields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Required. A field mask to restrict which fields on each person are returned. Multiple fields can be specified by separating them with commas. Valid values are: * addresses * ageRanges * biographies * birthdays * calendarUrls * clientData * coverPhotos * emailAddresses * events * externalIds * genders * imClients * interests * locales * locations * memberships * metadata * miscKeywords * names * nicknames * occupations * organizations * phoneNumbers * photos * relations * sipAddresses * skills * urls * userDefined\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"google-fieldmask\"\n      }\n     },\n     {\n      \"name\": \"peopleId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Identifier segment peopleId of the resource name.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/ListConnectionsResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/v1/otherContacts\": {\n   \"get\": {\n    \"operationId\": \"people.otherContacts.list\",\n    \"description\": \"List all \\\"Other contacts\\\", that is contacts that are not in a contact group. \\\"Other contacts\\\" are typically auto created contacts from interactions. Sync tokens expire 7 days after the full sync. A request with an expired sync token will get an error with an [google.rpc.ErrorInfo](https://cloud.google.com/apis/design/errors#error_info) with reason \\\"EXPIRED_SYNC_TOKEN\\\". In the case of such an error clients should make a full sync request without a `sync_token`. The first page of a full sync request has an additional quota. If the quota is exceeded, a 429 error will be returned. This quota is fixed and can not be increased. When the `sync_token` is specified, resources deleted since the last sync will be returned as a person with `PersonMetadata.deleted` set to true. When the `page_token` or `sync_token` is specified, all other request parameters must match the first call. Writes may have a propagation delay of several minutes for sync requests. Incremental syncs are not intended for read-after-write use cases. See example usage at [List the user's other contacts that have changed](/people/v1/other-contacts#list_the_users_other_contacts_that_have_changed).\",\n    \"parameters\": [\n     {\n      \"name\": \"syncToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. A sync token, received from a previous response `next_sync_token` Provide this to retrieve only the resources changed since the last request. When syncing, all other parameters provided to `otherContacts.list` must match the first call that provided the sync token. More details about sync behavior at `otherContacts.list`.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"pageSize\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. The number of \\\"Other contacts\\\" to include in the response. Valid values are between 1 and 1000, inclusive. Defaults to 100 if not set or set to 0.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"readMask\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Required. A field mask to restrict which fields on each person are returned. Multiple fields can be specified by separating them with commas. What values are valid depend on what ReadSourceType is used. If READ_SOURCE_TYPE_CONTACT is used, valid values are: * emailAddresses * metadata * names * phoneNumbers * photos If READ_SOURCE_TYPE_PROFILE is used, valid values are: * addresses * ageRanges * biographies * birthdays * calendarUrls * clientData * coverPhotos * emailAddresses * events * externalIds * genders * imClients * interests * locales * locations * memberships * metadata * miscKeywords * names * nicknames * occupations * organizations * phoneNumbers * photos * relations * sipAddresses * skills * urls * userDefined\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"google-fieldmask\"\n      }\n     },\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. A page token, received from a previous response `next_page_token`. Provide this to retrieve the subsequent page. When paginating, all other parameters provided to `otherContacts.list` must match the first call that provided the page token.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"requestSyncToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. Whether the response should return `next_sync_token` on the last page of results. It can be used to get incremental changes since the last request by setting it on the request `sync_token`. More details about sync behavior at `otherContacts.list`.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"sources\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. A mask of what source types to return. Defaults to READ_SOURCE_TYPE_CONTACT if not set. Possible values for this field are: * READ_SOURCE_TYPE_CONTACT * READ_SOURCE_TYPE_CONTACT,READ_SOURCE_TYPE_PROFILE Specifying READ_SOURCE_TYPE_PROFILE without specifying READ_SOURCE_TYPE_CONTACT is not permitted.\",\n      \"schema\": {\n       \"type\": \"array\",\n       \"items\": {\n        \"type\": \"string\",\n        \"enum\": [\n         \"READ_SOURCE_TYPE_UNSPECIFIED\",\n         \"READ_SOURCE_TYPE_PROFILE\",\n         \"READ_SOURCE_TYPE_CONTACT\",\n         \"READ_SOURCE_TYPE_DOMAIN_CONTACT\",\n         \"READ_SOURCE_TYPE_OTHER_CONTACT\"\n        ]\n       }\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/ListOtherContactsResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/v1/otherContacts/{otherContactsId}:copyOtherContactToMyContactsGroup\": {\n   \"post\": {\n    \"operationId\": \"people.otherContacts.copyOtherContactToMyContactsGroup\",\n    \"description\": \"Copies an \\\"Other contact\\\" to a new contact in the user's \\\"myContacts\\\" group Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.\",\n    \"parameters\": [\n     {\n      \"name\": \"otherContactsId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Identifier segment otherContactsId of the resource name.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Person\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/CopyOtherContactToMyContactsGroupRequest\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/v1/otherContacts:search\": {\n   \"get\": {\n    \"operationId\": \"people.otherContacts.search\",\n    \"description\": \"Provides a list of contacts in the authenticated user's other contacts that matches the search query. The query matches on a contact's `names`, `emailAddresses`, and `phoneNumbers` fields that are from the OTHER_CONTACT source. **IMPORTANT**: Before searching, clients should send a warmup request with an empty query to update the cache. See https://developers.google.com/people/v1/other-contacts#search_the_users_other_contacts\",\n    \"parameters\": [\n     {\n      \"name\": \"query\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Required. The plain-text query for the request. The query is used to match prefix phrases of the fields on a person. For example, a person with name \\\"foo name\\\" matches queries such as \\\"f\\\", \\\"fo\\\", \\\"foo\\\", \\\"foo n\\\", \\\"nam\\\", etc., but not \\\"oo n\\\".\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"pageSize\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. The number of results to return. Defaults to 10 if field is not set, or set to 0. Values greater than 30 will be capped to 30.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"readMask\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Required. A field mask to restrict which fields on each person are returned. Multiple fields can be specified by separating them with commas. Valid values are: * emailAddresses * metadata * names * phoneNumbers\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"google-fieldmask\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/SearchResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/v1/contactGroups\": {\n   \"post\": {\n    \"operationId\": \"people.contactGroups.create\",\n    \"description\": \"Create a new contact group owned by the authenticated user. Created contact group names must be unique to the users contact groups. Attempting to create a group with a duplicate name will return a HTTP 409 error. Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.\",\n    \"parameters\": [\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/ContactGroup\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/CreateContactGroupRequest\"\n       }\n      }\n     }\n    }\n   },\n   \"get\": {\n    \"operationId\": \"people.contactGroups.list\",\n    \"description\": \"List all contact groups owned by the authenticated user. Members of the contact groups are not populated.\",\n    \"parameters\": [\n     {\n      \"name\": \"pageSize\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. The maximum number of resources to return. Valid values are between 1 and 1000, inclusive. Defaults to 30 if not set or set to 0.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"groupFields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. A field mask to restrict which fields on the group are returned. Defaults to `metadata`, `groupType`, `memberCount`, and `name` if not set or set to empty. Valid fields are: * clientData * groupType * memberCount * metadata * name\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"google-fieldmask\"\n      }\n     },\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. The next_page_token value returned from a previous call to [ListContactGroups](/people/api/rest/v1/contactgroups/list). Requests the next page of resources.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"syncToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. A sync token, returned by a previous call to `contactgroups.list`. Only resources changed since the sync token was created will be returned.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/ListContactGroupsResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/v1/contactGroups/{contactGroupsId}\": {\n   \"get\": {\n    \"operationId\": \"people.contactGroups.get\",\n    \"description\": \"Get a specific contact group owned by the authenticated user by specifying a contact group resource name.\",\n    \"parameters\": [\n     {\n      \"name\": \"maxMembers\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. Specifies the maximum number of members to return. Defaults to 0 if not set, which will return zero members.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"groupFields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. A field mask to restrict which fields on the group are returned. Defaults to `metadata`, `groupType`, `memberCount`, and `name` if not set or set to empty. Valid fields are: * clientData * groupType * memberCount * metadata * name\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"google-fieldmask\"\n      }\n     },\n     {\n      \"name\": \"contactGroupsId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Identifier segment contactGroupsId of the resource name.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/ContactGroup\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   },\n   \"put\": {\n    \"operationId\": \"people.contactGroups.update\",\n    \"description\": \"Update the name of an existing contact group owned by the authenticated user. Updated contact group names must be unique to the users contact groups. Attempting to create a group with a duplicate name will return a HTTP 409 error. Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.\",\n    \"parameters\": [\n     {\n      \"name\": \"contactGroupsId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Identifier segment contactGroupsId of the resource name.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/ContactGroup\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/UpdateContactGroupRequest\"\n       }\n      }\n     }\n    }\n   },\n   \"delete\": {\n    \"operationId\": \"people.contactGroups.delete\",\n    \"description\": \"Delete an existing contact group owned by the authenticated user by specifying a contact group resource name. Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.\",\n    \"parameters\": [\n     {\n      \"name\": \"deleteContacts\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. Set to true to also delete the contacts in the specified group.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"contactGroupsId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Identifier segment contactGroupsId of the resource name.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Empty\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/v1/contactGroups:batchGet\": {\n   \"get\": {\n    \"operationId\": \"people.contactGroups.batchGet\",\n    \"description\": \"Get a list of contact groups owned by the authenticated user by specifying a list of contact group resource names.\",\n    \"parameters\": [\n     {\n      \"name\": \"groupFields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. A field mask to restrict which fields on the group are returned. Defaults to `metadata`, `groupType`, `memberCount`, and `name` if not set or set to empty. Valid fields are: * clientData * groupType * memberCount * metadata * name\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"google-fieldmask\"\n      }\n     },\n     {\n      \"name\": \"resourceNames\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Required. The resource names of the contact groups to get. There is a maximum of 200 resource names.\",\n      \"schema\": {\n       \"type\": \"array\",\n       \"items\": {\n        \"type\": \"string\"\n       }\n      }\n     },\n     {\n      \"name\": \"maxMembers\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. Specifies the maximum number of members to return for each group. Defaults to 0 if not set, which will return zero members.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/BatchGetContactGroupsResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/v1/contactGroups/{contactGroupsId}/members:modify\": {\n   \"post\": {\n    \"operationId\": \"people.contactGroups.members.modify\",\n    \"description\": \"Modify the members of a contact group owned by the authenticated user. The only system contact groups that can have members added are `contactGroups/myContacts` and `contactGroups/starred`. Other system contact groups are deprecated and can only have contacts removed.\",\n    \"parameters\": [\n     {\n      \"name\": \"contactGroupsId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Identifier segment contactGroupsId of the resource name.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/ModifyContactGroupMembersResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/ModifyContactGroupMembersRequest\"\n       }\n      }\n     }\n    }\n   }\n  }\n },\n \"components\": {\n  \"schemas\": {\n   \"ExternalId\": {\n    \"description\": \"An identifier from an external entity related to the person.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"formattedType\": {\n      \"description\": \"Output only. The type of the event translated and formatted in the viewer's account locale or the `Accept-Language` HTTP header locale.\",\n      \"type\": \"string\"\n     },\n     \"value\": {\n      \"description\": \"The value of the external ID.\",\n      \"type\": \"string\"\n     },\n     \"type\": {\n      \"description\": \"The type of the external ID. The type can be custom or one of these predefined values: * `account` * `customer` * `loginId` * `network` * `organization`\",\n      \"type\": \"string\"\n     },\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     }\n    }\n   },\n   \"ListDirectoryPeopleResponse\": {\n    \"description\": \"The response to a request for the authenticated user's domain directory.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"nextSyncToken\": {\n      \"description\": \"A token, which can be sent as `sync_token` to retrieve changes since the last request. Request must set `request_sync_token` to return the sync token.\",\n      \"type\": \"string\"\n     },\n     \"nextPageToken\": {\n      \"description\": \"A token, which can be sent as `page_token` to retrieve the next page. If this field is omitted, there are no subsequent pages.\",\n      \"type\": \"string\"\n     },\n     \"people\": {\n      \"description\": \"The list of people in the domain directory.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Person\"\n      }\n     }\n    }\n   },\n   \"RelationshipStatus\": {\n    \"description\": \"**DEPRECATED**: No data will be returned A person's relationship status.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     },\n     \"formattedValue\": {\n      \"description\": \"Output only. The value of the relationship status translated and formatted in the viewer's account locale or the `Accept-Language` HTTP header locale.\",\n      \"type\": \"string\"\n     },\n     \"value\": {\n      \"description\": \"The relationship status. The value can be custom or one of these predefined values: * `single` * `inARelationship` * `engaged` * `married` * `itsComplicated` * `openRelationship` * `widowed` * `inDomesticPartnership` * `inCivilUnion`\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"MiscKeyword\": {\n    \"description\": \"A person's miscellaneous keyword.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"type\": {\n      \"description\": \"The miscellaneous keyword type.\",\n      \"type\": \"string\",\n      \"enum\": [\n       \"TYPE_UNSPECIFIED\",\n       \"OUTLOOK_BILLING_INFORMATION\",\n       \"OUTLOOK_DIRECTORY_SERVER\",\n       \"OUTLOOK_KEYWORD\",\n       \"OUTLOOK_MILEAGE\",\n       \"OUTLOOK_PRIORITY\",\n       \"OUTLOOK_SENSITIVITY\",\n       \"OUTLOOK_SUBJECT\",\n       \"OUTLOOK_USER\",\n       \"HOME\",\n       \"WORK\",\n       \"OTHER\"\n      ]\n     },\n     \"formattedType\": {\n      \"description\": \"Output only. The type of the miscellaneous keyword translated and formatted in the viewer's account locale or the `Accept-Language` HTTP header locale.\",\n      \"type\": \"string\"\n     },\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     },\n     \"value\": {\n      \"description\": \"The value of the miscellaneous keyword.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"UpdateContactPhotoRequest\": {\n    \"description\": \"A request to update an existing contact's photo. All requests must have a valid photo format: JPEG or PNG.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"personFields\": {\n      \"description\": \"Optional. A field mask to restrict which fields on the person are returned. Multiple fields can be specified by separating them with commas. Defaults to empty if not set, which will skip the post mutate get. Valid values are: * addresses * ageRanges * biographies * birthdays * calendarUrls * clientData * coverPhotos * emailAddresses * events * externalIds * genders * imClients * interests * locales * locations * memberships * metadata * miscKeywords * names * nicknames * occupations * organizations * phoneNumbers * photos * relations * sipAddresses * skills * urls * userDefined\",\n      \"type\": \"string\",\n      \"format\": \"google-fieldmask\"\n     },\n     \"sources\": {\n      \"description\": \"Optional. A mask of what source types to return. Defaults to READ_SOURCE_TYPE_CONTACT and READ_SOURCE_TYPE_PROFILE if not set.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\",\n       \"enum\": [\n        \"READ_SOURCE_TYPE_UNSPECIFIED\",\n        \"READ_SOURCE_TYPE_PROFILE\",\n        \"READ_SOURCE_TYPE_CONTACT\",\n        \"READ_SOURCE_TYPE_DOMAIN_CONTACT\",\n        \"READ_SOURCE_TYPE_OTHER_CONTACT\"\n       ]\n      }\n     },\n     \"photoBytes\": {\n      \"description\": \"Required. Raw photo bytes\",\n      \"type\": \"string\",\n      \"format\": \"byte\"\n     }\n    }\n   },\n   \"Photo\": {\n    \"description\": \"A person's photo. A picture shown next to the person's name to help others recognize the person.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     },\n     \"url\": {\n      \"description\": \"The URL of the photo. You can change the desired size by appending a query parameter `sz={size}` at the end of the url, where {size} is the size in pixels. Example: https://lh3.googleusercontent.com/-T_wVWLlmg7w/AAAAAAAAAAI/AAAAAAAABa8/00gzXvDBYqw/s100/photo.jpg?sz=50\",\n      \"type\": \"string\"\n     },\n     \"default\": {\n      \"description\": \"True if the photo is a default photo; false if the photo is a user-provided photo.\",\n      \"type\": \"boolean\"\n     }\n    }\n   },\n   \"CopyOtherContactToMyContactsGroupRequest\": {\n    \"description\": \"A request to copy an \\\"Other contact\\\" to my contacts group.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"sources\": {\n      \"description\": \"Optional. A mask of what source types to return. Defaults to READ_SOURCE_TYPE_CONTACT and READ_SOURCE_TYPE_PROFILE if not set.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\",\n       \"enum\": [\n        \"READ_SOURCE_TYPE_UNSPECIFIED\",\n        \"READ_SOURCE_TYPE_PROFILE\",\n        \"READ_SOURCE_TYPE_CONTACT\",\n        \"READ_SOURCE_TYPE_DOMAIN_CONTACT\",\n        \"READ_SOURCE_TYPE_OTHER_CONTACT\"\n       ]\n      }\n     },\n     \"copyMask\": {\n      \"description\": \"Required. A field mask to restrict which fields are copied into the new contact. Valid values are: * emailAddresses * names * phoneNumbers\",\n      \"type\": \"string\",\n      \"format\": \"google-fieldmask\"\n     },\n     \"readMask\": {\n      \"description\": \"Optional. A field mask to restrict which fields on the person are returned. Multiple fields can be specified by separating them with commas. Defaults to the copy mask with metadata and membership fields if not set. Valid values are: * addresses * ageRanges * biographies * birthdays * calendarUrls * clientData * coverPhotos * emailAddresses * events * externalIds * genders * imClients * interests * locales * locations * memberships * metadata * miscKeywords * names * nicknames * occupations * organizations * phoneNumbers * photos * relations * sipAddresses * skills * urls * userDefined\",\n      \"type\": \"string\",\n      \"format\": \"google-fieldmask\"\n     }\n    }\n   },\n   \"SearchDirectoryPeopleResponse\": {\n    \"description\": \"The response to a request for people in the authenticated user's domain directory that match the specified query.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"people\": {\n      \"description\": \"The list of people in the domain directory that match the query.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Person\"\n      }\n     },\n     \"nextPageToken\": {\n      \"description\": \"A token, which can be sent as `page_token` to retrieve the next page. If this field is omitted, there are no subsequent pages.\",\n      \"type\": \"string\"\n     },\n     \"totalSize\": {\n      \"description\": \"The total number of items in the list without pagination.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     }\n    }\n   },\n   \"PhoneNumber\": {\n    \"description\": \"A person's phone number.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"type\": {\n      \"description\": \"The type of the phone number. The type can be custom or one of these predefined values: * `home` * `work` * `mobile` * `homeFax` * `workFax` * `otherFax` * `pager` * `workMobile` * `workPager` * `main` * `googleVoice` * `other`\",\n      \"type\": \"string\"\n     },\n     \"value\": {\n      \"description\": \"The phone number.\",\n      \"type\": \"string\"\n     },\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     },\n     \"formattedType\": {\n      \"description\": \"Output only. The type of the phone number translated and formatted in the viewer's account locale or the `Accept-Language` HTTP header locale.\",\n      \"type\": \"string\"\n     },\n     \"canonicalForm\": {\n      \"description\": \"Output only. The canonicalized [ITU-T E.164](https://law.resource.org/pub/us/cfr/ibr/004/itu-t.E.164.1.2008.pdf) form of the phone number.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"ModifyContactGroupMembersResponse\": {\n    \"description\": \"The response to a modify contact group members request.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"notFoundResourceNames\": {\n      \"description\": \"The contact people resource names that were not found.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"canNotRemoveLastContactGroupResourceNames\": {\n      \"description\": \"The contact people resource names that cannot be removed from their last contact group.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     }\n    }\n   },\n   \"Skill\": {\n    \"description\": \"A skill that the person has.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     },\n     \"value\": {\n      \"description\": \"The skill; for example, `underwater basket weaving`.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"Occupation\": {\n    \"description\": \"A person's occupation.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"value\": {\n      \"description\": \"The occupation; for example, `carpenter`.\",\n      \"type\": \"string\"\n     },\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     }\n    }\n   },\n   \"Source\": {\n    \"description\": \"The source of a field.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"updateTime\": {\n      \"description\": \"Output only. **Only populated in `person.metadata.sources`.** Last update timestamp of this source.\",\n      \"type\": \"string\",\n      \"format\": \"google-datetime\"\n     },\n     \"etag\": {\n      \"description\": \"**Only populated in `person.metadata.sources`.** The [HTTP entity tag](https://en.wikipedia.org/wiki/HTTP_ETag) of the source. Used for web cache validation.\",\n      \"type\": \"string\"\n     },\n     \"id\": {\n      \"description\": \"The unique identifier within the source type generated by the server.\",\n      \"type\": \"string\"\n     },\n     \"profileMetadata\": {\n      \"$ref\": \"#/components/schemas/ProfileMetadata\"\n     },\n     \"type\": {\n      \"description\": \"The source type.\",\n      \"type\": \"string\",\n      \"enum\": [\n       \"SOURCE_TYPE_UNSPECIFIED\",\n       \"ACCOUNT\",\n       \"PROFILE\",\n       \"DOMAIN_PROFILE\",\n       \"CONTACT\",\n       \"OTHER_CONTACT\",\n       \"DOMAIN_CONTACT\"\n      ]\n     }\n    }\n   },\n   \"ModifyContactGroupMembersRequest\": {\n    \"description\": \"A request to modify an existing contact group's members. Contacts can be removed from any group but they can only be added to a user group or \\\"myContacts\\\" or \\\"starred\\\" system groups.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"resourceNamesToAdd\": {\n      \"description\": \"Optional. The resource names of the contact people to add in the form of `people/{person_id}`. The total number of resource names in `resource_names_to_add` and `resource_names_to_remove` must be less than or equal to 1000.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"resourceNamesToRemove\": {\n      \"description\": \"Optional. The resource names of the contact people to remove in the form of `people/{person_id}`. The total number of resource names in `resource_names_to_add` and `resource_names_to_remove` must be less than or equal to 1000.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     }\n    }\n   },\n   \"FileAs\": {\n    \"description\": \"The name that should be used to sort the person in a list.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"value\": {\n      \"description\": \"The file-as value\",\n      \"type\": \"string\"\n     },\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     }\n    }\n   },\n   \"BatchUpdateContactsResponse\": {\n    \"description\": \"If not successful, returns BatchUpdateContactsErrorDetails, a list of errors corresponding to each contact. The response to a request to update a batch of contacts.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"updateResult\": {\n      \"description\": \"A map of resource names to the contacts that were updated, unless the request `read_mask` is empty.\",\n      \"type\": \"object\",\n      \"additionalProperties\": {\n       \"$ref\": \"#/components/schemas/PersonResponse\"\n      }\n     }\n    }\n   },\n   \"UpdateContactGroupRequest\": {\n    \"description\": \"A request to update an existing user contact group. All updated fields will be replaced.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"readGroupFields\": {\n      \"description\": \"Optional. A field mask to restrict which fields on the group are returned. Defaults to `metadata`, `groupType`, and `name` if not set or set to empty. Valid fields are: * clientData * groupType * memberCount * metadata * name\",\n      \"type\": \"string\",\n      \"format\": \"google-fieldmask\"\n     },\n     \"updateGroupFields\": {\n      \"description\": \"Optional. A field mask to restrict which fields on the group are updated. Multiple fields can be specified by separating them with commas. Defaults to `name` if not set or set to empty. Updated fields are replaced. Valid values are: * clientData * name\",\n      \"type\": \"string\",\n      \"format\": \"google-fieldmask\"\n     },\n     \"contactGroup\": {\n      \"$ref\": \"#/components/schemas/ContactGroup\"\n     }\n    }\n   },\n   \"ListOtherContactsResponse\": {\n    \"description\": \"The response to a request for the authenticated user's \\\"Other contacts\\\".\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"nextPageToken\": {\n      \"description\": \"A token, which can be sent as `page_token` to retrieve the next page. If this field is omitted, there are no subsequent pages.\",\n      \"type\": \"string\"\n     },\n     \"otherContacts\": {\n      \"description\": \"The list of \\\"Other contacts\\\" returned as Person resources. \\\"Other contacts\\\" support a limited subset of fields. See ListOtherContactsRequest.request_mask for more detailed information.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Person\"\n      }\n     },\n     \"totalSize\": {\n      \"description\": \"The total number of other contacts in the list without pagination.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     },\n     \"nextSyncToken\": {\n      \"description\": \"A token, which can be sent as `sync_token` to retrieve changes since the last request. Request must set `request_sync_token` to return the sync token.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"Location\": {\n    \"description\": \"A person's location.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"current\": {\n      \"description\": \"Whether the location is the current location.\",\n      \"type\": \"boolean\"\n     },\n     \"deskCode\": {\n      \"description\": \"The individual desk location.\",\n      \"type\": \"string\"\n     },\n     \"value\": {\n      \"description\": \"The free-form value of the location.\",\n      \"type\": \"string\"\n     },\n     \"floor\": {\n      \"description\": \"The floor name or number.\",\n      \"type\": \"string\"\n     },\n     \"type\": {\n      \"description\": \"The type of the location. The type can be custom or one of these predefined values: * `desk` * `grewUp`\",\n      \"type\": \"string\"\n     },\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     },\n     \"floorSection\": {\n      \"description\": \"The floor section in `floor_name`.\",\n      \"type\": \"string\"\n     },\n     \"buildingId\": {\n      \"description\": \"The building identifier.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"ListConnectionsResponse\": {\n    \"description\": \"The response to a request for the authenticated user's connections.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"totalItems\": {\n      \"description\": \"The total number of items in the list without pagination.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     },\n     \"nextSyncToken\": {\n      \"description\": \"A token, which can be sent as `sync_token` to retrieve changes since the last request. Request must set `request_sync_token` to return the sync token. When the response is paginated, only the last page will contain `nextSyncToken`.\",\n      \"type\": \"string\"\n     },\n     \"nextPageToken\": {\n      \"description\": \"A token, which can be sent as `page_token` to retrieve the next page. If this field is omitted, there are no subsequent pages.\",\n      \"type\": \"string\"\n     },\n     \"totalPeople\": {\n      \"description\": \"**DEPRECATED** (Please use totalItems) The total number of people in the list without pagination.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     },\n     \"connections\": {\n      \"description\": \"The list of people that the requestor is connected to.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Person\"\n      }\n     }\n    }\n   },\n   \"Birthday\": {\n    \"description\": \"A person's birthday. At least one of the `date` and `text` fields are specified. The `date` and `text` fields typically represent the same date, but are not guaranteed to. Clients should always set the `date` field when mutating birthdays.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     },\n     \"date\": {\n      \"$ref\": \"#/components/schemas/Date\"\n     },\n     \"text\": {\n      \"description\": \"Prefer to use the `date` field if set. A free-form string representing the user's birthday. This value is not validated.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"ContactGroupMembership\": {\n    \"description\": \"A Google contact group membership.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"contactGroupId\": {\n      \"description\": \"Output only. The contact group ID for the contact group membership.\",\n      \"type\": \"string\"\n     },\n     \"contactGroupResourceName\": {\n      \"description\": \"The resource name for the contact group, assigned by the server. An ASCII string, in the form of `contactGroups/{contact_group_id}`. Only contact_group_resource_name can be used for modifying memberships. Any contact group membership can be removed, but only user group or \\\"myContacts\\\" or \\\"starred\\\" system groups memberships can be added. A contact must always have at least one contact group membership.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"ImClient\": {\n    \"description\": \"A person's instant messaging client.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"protocol\": {\n      \"description\": \"The protocol of the IM client. The protocol can be custom or one of these predefined values: * `aim` * `msn` * `yahoo` * `skype` * `qq` * `googleTalk` * `icq` * `jabber` * `netMeeting`\",\n      \"type\": \"string\"\n     },\n     \"formattedProtocol\": {\n      \"description\": \"Output only. The protocol of the IM client formatted in the viewer's account locale or the `Accept-Language` HTTP header locale.\",\n      \"type\": \"string\"\n     },\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     },\n     \"username\": {\n      \"description\": \"The user name used in the IM client.\",\n      \"type\": \"string\"\n     },\n     \"formattedType\": {\n      \"description\": \"Output only. The type of the IM client translated and formatted in the viewer's account locale or the `Accept-Language` HTTP header locale.\",\n      \"type\": \"string\"\n     },\n     \"type\": {\n      \"description\": \"The type of the IM client. The type can be custom or one of these predefined values: * `home` * `work` * `other`\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"ProfileMetadata\": {\n    \"description\": \"The metadata about a profile.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"userTypes\": {\n      \"description\": \"Output only. The user types.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\",\n       \"enum\": [\n        \"USER_TYPE_UNKNOWN\",\n        \"GOOGLE_USER\",\n        \"GPLUS_USER\",\n        \"GOOGLE_APPS_USER\"\n       ]\n      }\n     },\n     \"objectType\": {\n      \"description\": \"Output only. The profile object type.\",\n      \"type\": \"string\",\n      \"enum\": [\n       \"OBJECT_TYPE_UNSPECIFIED\",\n       \"PERSON\",\n       \"PAGE\"\n      ]\n     }\n    }\n   },\n   \"Relation\": {\n    \"description\": \"A person's relation to another person.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"formattedType\": {\n      \"description\": \"Output only. The type of the relation translated and formatted in the viewer's account locale or the locale specified in the Accept-Language HTTP header.\",\n      \"type\": \"string\"\n     },\n     \"type\": {\n      \"description\": \"The person's relation to the other person. The type can be custom or one of these predefined values: * `spouse` * `child` * `mother` * `father` * `parent` * `brother` * `sister` * `friend` * `relative` * `domesticPartner` * `manager` * `assistant` * `referredBy` * `partner`\",\n      \"type\": \"string\"\n     },\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     },\n     \"person\": {\n      \"description\": \"The name of the other person this relation refers to.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"Gender\": {\n    \"description\": \"A person's gender.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"addressMeAs\": {\n      \"description\": \"Free form text field for pronouns that should be used to address the person. Common values are: * `he`/`him` * `she`/`her` * `they`/`them`\",\n      \"type\": \"string\"\n     },\n     \"value\": {\n      \"description\": \"The gender for the person. The gender can be custom or one of these predefined values: * `male` * `female` * `unspecified`\",\n      \"type\": \"string\"\n     },\n     \"formattedValue\": {\n      \"description\": \"Output only. The value of the gender translated and formatted in the viewer's account locale or the `Accept-Language` HTTP header locale. Unspecified or custom value are not localized.\",\n      \"type\": \"string\"\n     },\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     }\n    }\n   },\n   \"Tagline\": {\n    \"description\": \"**DEPRECATED**: No data will be returned A brief one-line description of the person.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     },\n     \"value\": {\n      \"description\": \"The tagline.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"Nickname\": {\n    \"description\": \"A person's nickname.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     },\n     \"type\": {\n      \"description\": \"The type of the nickname.\",\n      \"type\": \"string\",\n      \"enum\": [\n       \"DEFAULT\",\n       \"MAIDEN_NAME\",\n       \"INITIALS\",\n       \"GPLUS\",\n       \"OTHER_NAME\",\n       \"ALTERNATE_NAME\",\n       \"SHORT_NAME\"\n      ]\n     },\n     \"value\": {\n      \"description\": \"The nickname.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"AgeRangeType\": {\n    \"description\": \"A person's age range.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     },\n     \"ageRange\": {\n      \"description\": \"The age range.\",\n      \"type\": \"string\",\n      \"enum\": [\n       \"AGE_RANGE_UNSPECIFIED\",\n       \"LESS_THAN_EIGHTEEN\",\n       \"EIGHTEEN_TO_TWENTY\",\n       \"TWENTY_ONE_OR_OLDER\"\n      ]\n     }\n    }\n   },\n   \"Empty\": {\n    \"description\": \"A generic empty message that you can re-use to avoid defining duplicated empty messages in your APIs. A typical example is to use it as the request or the response type of an API method. For instance: service Foo { rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); }\",\n    \"type\": \"object\",\n    \"properties\": {}\n   },\n   \"BatchDeleteContactsRequest\": {\n    \"description\": \"A request to delete a batch of existing contacts.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"resourceNames\": {\n      \"description\": \"Required. The resource names of the contact to delete. It's repeatable. Allows up to 500 resource names in a single request.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     }\n    }\n   },\n   \"SearchResponse\": {\n    \"description\": \"The response to a search request for the authenticated user, given a query.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"results\": {\n      \"description\": \"The results of the request.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/SearchResult\"\n      }\n     }\n    }\n   },\n   \"Residence\": {\n    \"description\": \"**DEPRECATED**: Please use `person.locations` instead. A person's past or current residence.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     },\n     \"value\": {\n      \"description\": \"The address of the residence.\",\n      \"type\": \"string\"\n     },\n     \"current\": {\n      \"description\": \"True if the residence is the person's current residence; false if the residence is a past residence.\",\n      \"type\": \"boolean\"\n     }\n    }\n   },\n   \"ClientData\": {\n    \"description\": \"Arbitrary client data that is populated by clients. Duplicate keys and values are allowed.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"key\": {\n      \"description\": \"The client specified key of the client data.\",\n      \"type\": \"string\"\n     },\n     \"value\": {\n      \"description\": \"The client specified value of the client data.\",\n      \"type\": \"string\"\n     },\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     }\n    }\n   },\n   \"EmailAddress\": {\n    \"description\": \"A person's email address.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"value\": {\n      \"description\": \"The email address.\",\n      \"type\": \"string\"\n     },\n     \"type\": {\n      \"description\": \"The type of the email address. The type can be custom or one of these predefined values: * `home` * `work` * `other`\",\n      \"type\": \"string\"\n     },\n     \"displayName\": {\n      \"description\": \"The display name of the email.\",\n      \"type\": \"string\"\n     },\n     \"formattedType\": {\n      \"description\": \"Output only. The type of the email address translated and formatted in the viewer's account locale or the `Accept-Language` HTTP header locale.\",\n      \"type\": \"string\"\n     },\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     }\n    }\n   },\n   \"Status\": {\n    \"description\": \"The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors).\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"message\": {\n      \"description\": \"A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the google.rpc.Status.details field, or localized by the client.\",\n      \"type\": \"string\"\n     },\n     \"details\": {\n      \"description\": \"A list of messages that carry the error details. There is a common set of message types for APIs to use.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"object\",\n       \"additionalProperties\": {\n        \"description\": \"Properties of the object. Contains field @type with type URL.\"\n       }\n      }\n     },\n     \"code\": {\n      \"description\": \"The status code, which should be an enum value of google.rpc.Code.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     }\n    }\n   },\n   \"BraggingRights\": {\n    \"description\": \"**DEPRECATED**: No data will be returned A person's bragging rights.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"value\": {\n      \"description\": \"The bragging rights; for example, `climbed mount everest`.\",\n      \"type\": \"string\"\n     },\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     }\n    }\n   },\n   \"Biography\": {\n    \"description\": \"A person's short biography.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     },\n     \"contentType\": {\n      \"description\": \"The content type of the biography.\",\n      \"type\": \"string\",\n      \"enum\": [\n       \"CONTENT_TYPE_UNSPECIFIED\",\n       \"TEXT_PLAIN\",\n       \"TEXT_HTML\"\n      ]\n     },\n     \"value\": {\n      \"description\": \"The short biography.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"Organization\": {\n    \"description\": \"A person's past or current organization. Overlapping date ranges are permitted.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"startDate\": {\n      \"$ref\": \"#/components/schemas/Date\"\n     },\n     \"costCenter\": {\n      \"description\": \"The person's cost center at the organization.\",\n      \"type\": \"string\"\n     },\n     \"current\": {\n      \"description\": \"True if the organization is the person's current organization; false if the organization is a past organization.\",\n      \"type\": \"boolean\"\n     },\n     \"fullTimeEquivalentMillipercent\": {\n      \"description\": \"The person's full-time equivalent millipercent within the organization (100000 = 100%).\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     },\n     \"endDate\": {\n      \"$ref\": \"#/components/schemas/Date\"\n     },\n     \"formattedType\": {\n      \"description\": \"Output only. The type of the organization translated and formatted in the viewer's account locale or the `Accept-Language` HTTP header locale.\",\n      \"type\": \"string\"\n     },\n     \"department\": {\n      \"description\": \"The person's department at the organization.\",\n      \"type\": \"string\"\n     },\n     \"location\": {\n      \"description\": \"The location of the organization office the person works at.\",\n      \"type\": \"string\"\n     },\n     \"symbol\": {\n      \"description\": \"The symbol associated with the organization; for example, a stock ticker symbol, abbreviation, or acronym.\",\n      \"type\": \"string\"\n     },\n     \"title\": {\n      \"description\": \"The person's job title at the organization.\",\n      \"type\": \"string\"\n     },\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     },\n     \"jobDescription\": {\n      \"description\": \"The person's job description at the organization.\",\n      \"type\": \"string\"\n     },\n     \"phoneticName\": {\n      \"description\": \"The phonetic name of the organization.\",\n      \"type\": \"string\"\n     },\n     \"name\": {\n      \"description\": \"The name of the organization.\",\n      \"type\": \"string\"\n     },\n     \"domain\": {\n      \"description\": \"The domain name associated with the organization; for example, `google.com`.\",\n      \"type\": \"string\"\n     },\n     \"type\": {\n      \"description\": \"The type of the organization. The type can be custom or one of these predefined values: * `work` * `school`\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"DeleteContactPhotoResponse\": {\n    \"description\": \"The response for deleting a contact's photo.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"person\": {\n      \"$ref\": \"#/components/schemas/Person\"\n     }\n    }\n   },\n   \"ContactToCreate\": {\n    \"description\": \"A wrapper that contains the person data to populate a newly created source.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"contactPerson\": {\n      \"$ref\": \"#/components/schemas/Person\"\n     }\n    }\n   },\n   \"Membership\": {\n    \"description\": \"A person's membership in a group. Only contact group memberships can be modified.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     },\n     \"domainMembership\": {\n      \"$ref\": \"#/components/schemas/DomainMembership\"\n     },\n     \"contactGroupMembership\": {\n      \"$ref\": \"#/components/schemas/ContactGroupMembership\"\n     }\n    }\n   },\n   \"Locale\": {\n    \"description\": \"A person's locale preference.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"value\": {\n      \"description\": \"The well-formed [IETF BCP 47](https://tools.ietf.org/html/bcp47) language tag representing the locale.\",\n      \"type\": \"string\"\n     },\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     }\n    }\n   },\n   \"CalendarUrl\": {\n    \"description\": \"A person's calendar URL.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"type\": {\n      \"description\": \"The type of the calendar URL. The type can be custom or one of these predefined values: * `home` * `freeBusy` * `work`\",\n      \"type\": \"string\"\n     },\n     \"url\": {\n      \"description\": \"The calendar URL.\",\n      \"type\": \"string\"\n     },\n     \"formattedType\": {\n      \"description\": \"Output only. The type of the calendar URL translated and formatted in the viewer's account locale or the `Accept-Language` HTTP header locale.\",\n      \"type\": \"string\"\n     },\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     }\n    }\n   },\n   \"Date\": {\n    \"description\": \"Represents a whole or partial calendar date, such as a birthday. The time of day and time zone are either specified elsewhere or are insignificant. The date is relative to the Gregorian Calendar. This can represent one of the following: * A full date, with non-zero year, month, and day values. * A month and day, with a zero year (for example, an anniversary). * A year on its own, with a zero month and a zero day. * A year and month, with a zero day (for example, a credit card expiration date). Related types: * google.type.TimeOfDay * google.type.DateTime * google.protobuf.Timestamp\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"year\": {\n      \"description\": \"Year of the date. Must be from 1 to 9999, or 0 to specify a date without a year.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     },\n     \"month\": {\n      \"description\": \"Month of a year. Must be from 1 to 12, or 0 to specify a year without a month and day.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     },\n     \"day\": {\n      \"description\": \"Day of a month. Must be from 1 to 31 and valid for the year and month, or 0 to specify a year by itself or a year and month where the day isn't significant.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     }\n    }\n   },\n   \"BatchCreateContactsRequest\": {\n    \"description\": \"A request to create a batch of contacts.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"contacts\": {\n      \"description\": \"Required. The contact to create. Allows up to 200 contacts in a single request.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/ContactToCreate\"\n      }\n     },\n     \"readMask\": {\n      \"description\": \"Required. A field mask to restrict which fields on each person are returned in the response. Multiple fields can be specified by separating them with commas. If read mask is left empty, the post-mutate-get is skipped and no data will be returned in the response. Valid values are: * addresses * ageRanges * biographies * birthdays * calendarUrls * clientData * coverPhotos * emailAddresses * events * externalIds * genders * imClients * interests * locales * locations * memberships * metadata * miscKeywords * names * nicknames * occupations * organizations * phoneNumbers * photos * relations * sipAddresses * skills * urls * userDefined\",\n      \"type\": \"string\",\n      \"format\": \"google-fieldmask\"\n     },\n     \"sources\": {\n      \"description\": \"Optional. A mask of what source types to return in the post mutate read. Defaults to READ_SOURCE_TYPE_CONTACT and READ_SOURCE_TYPE_PROFILE if not set.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\",\n       \"enum\": [\n        \"READ_SOURCE_TYPE_UNSPECIFIED\",\n        \"READ_SOURCE_TYPE_PROFILE\",\n        \"READ_SOURCE_TYPE_CONTACT\",\n        \"READ_SOURCE_TYPE_DOMAIN_CONTACT\",\n        \"READ_SOURCE_TYPE_OTHER_CONTACT\"\n       ]\n      }\n     }\n    }\n   },\n   \"SearchResult\": {\n    \"description\": \"A result of a search query.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"person\": {\n      \"$ref\": \"#/components/schemas/Person\"\n     }\n    }\n   },\n   \"Name\": {\n    \"description\": \"A person's name. If the name is a mononym, the family name is empty.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"phoneticFamilyName\": {\n      \"description\": \"The family name spelled as it sounds.\",\n      \"type\": \"string\"\n     },\n     \"givenName\": {\n      \"description\": \"The given name.\",\n      \"type\": \"string\"\n     },\n     \"honorificPrefix\": {\n      \"description\": \"The honorific prefixes, such as `Mrs.` or `Dr.`\",\n      \"type\": \"string\"\n     },\n     \"phoneticMiddleName\": {\n      \"description\": \"The middle name(s) spelled as they sound.\",\n      \"type\": \"string\"\n     },\n     \"honorificSuffix\": {\n      \"description\": \"The honorific suffixes, such as `Jr.`\",\n      \"type\": \"string\"\n     },\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     },\n     \"displayNameLastFirst\": {\n      \"description\": \"Output only. The display name with the last name first formatted according to the locale specified by the viewer's account or the `Accept-Language` HTTP header.\",\n      \"type\": \"string\"\n     },\n     \"phoneticFullName\": {\n      \"description\": \"The full name spelled as it sounds.\",\n      \"type\": \"string\"\n     },\n     \"phoneticGivenName\": {\n      \"description\": \"The given name spelled as it sounds.\",\n      \"type\": \"string\"\n     },\n     \"phoneticHonorificSuffix\": {\n      \"description\": \"The honorific suffixes spelled as they sound.\",\n      \"type\": \"string\"\n     },\n     \"familyName\": {\n      \"description\": \"The family name.\",\n      \"type\": \"string\"\n     },\n     \"phoneticHonorificPrefix\": {\n      \"description\": \"The honorific prefixes spelled as they sound.\",\n      \"type\": \"string\"\n     },\n     \"displayName\": {\n      \"description\": \"Output only. The display name formatted according to the locale specified by the viewer's account or the `Accept-Language` HTTP header.\",\n      \"type\": \"string\"\n     },\n     \"unstructuredName\": {\n      \"description\": \"The free form name value.\",\n      \"type\": \"string\"\n     },\n     \"middleName\": {\n      \"description\": \"The middle name(s).\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"CoverPhoto\": {\n    \"description\": \"A person's cover photo. A large image shown on the person's profile page that represents who they are or what they care about.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"url\": {\n      \"description\": \"The URL of the cover photo.\",\n      \"type\": \"string\"\n     },\n     \"default\": {\n      \"description\": \"True if the cover photo is the default cover photo; false if the cover photo is a user-provided cover photo.\",\n      \"type\": \"boolean\"\n     },\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     }\n    }\n   },\n   \"GetPeopleResponse\": {\n    \"description\": \"The response to a get request for a list of people by resource name.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"responses\": {\n      \"description\": \"The response for each requested resource name.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/PersonResponse\"\n      }\n     }\n    }\n   },\n   \"ContactGroup\": {\n    \"description\": \"A contact group.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"clientData\": {\n      \"description\": \"The group's client data.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/GroupClientData\"\n      }\n     },\n     \"memberResourceNames\": {\n      \"description\": \"Output only. The list of contact person resource names that are members of the contact group. The field is only populated for GET requests and will only return as many members as `maxMembers` in the get request.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/ContactGroupMetadata\"\n     },\n     \"memberCount\": {\n      \"description\": \"Output only. The total number of contacts in the group irrespective of max members in specified in the request.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     },\n     \"resourceName\": {\n      \"description\": \"The resource name for the contact group, assigned by the server. An ASCII string, in the form of `contactGroups/{contact_group_id}`.\",\n      \"type\": \"string\"\n     },\n     \"groupType\": {\n      \"description\": \"Output only. The contact group type.\",\n      \"type\": \"string\",\n      \"enum\": [\n       \"GROUP_TYPE_UNSPECIFIED\",\n       \"USER_CONTACT_GROUP\",\n       \"SYSTEM_CONTACT_GROUP\"\n      ]\n     },\n     \"formattedName\": {\n      \"description\": \"Output only. The name translated and formatted in the viewer's account locale or the `Accept-Language` HTTP header locale for system groups names. Group names set by the owner are the same as name.\",\n      \"type\": \"string\"\n     },\n     \"etag\": {\n      \"description\": \"The [HTTP entity tag](https://en.wikipedia.org/wiki/HTTP_ETag) of the resource. Used for web cache validation.\",\n      \"type\": \"string\"\n     },\n     \"name\": {\n      \"description\": \"The contact group name set by the group owner or a system provided name for system groups. For [`contactGroups.create`](/people/api/rest/v1/contactGroups/create) or [`contactGroups.update`](/people/api/rest/v1/contactGroups/update) the name must be unique to the users contact groups. Attempting to create a group with a duplicate name will return a HTTP 409 error.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"CreateContactGroupRequest\": {\n    \"description\": \"A request to create a new contact group.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"readGroupFields\": {\n      \"description\": \"Optional. A field mask to restrict which fields on the group are returned. Defaults to `metadata`, `groupType`, and `name` if not set or set to empty. Valid fields are: * clientData * groupType * metadata * name\",\n      \"type\": \"string\",\n      \"format\": \"google-fieldmask\"\n     },\n     \"contactGroup\": {\n      \"$ref\": \"#/components/schemas/ContactGroup\"\n     }\n    }\n   },\n   \"UserDefined\": {\n    \"description\": \"Arbitrary user data that is populated by the end users.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"key\": {\n      \"description\": \"The end user specified key of the user defined data.\",\n      \"type\": \"string\"\n     },\n     \"value\": {\n      \"description\": \"The end user specified value of the user defined data.\",\n      \"type\": \"string\"\n     },\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     }\n    }\n   },\n   \"RelationshipInterest\": {\n    \"description\": \"**DEPRECATED**: No data will be returned A person's relationship interest .\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     },\n     \"value\": {\n      \"description\": \"The kind of relationship the person is looking for. The value can be custom or one of these predefined values: * `friend` * `date` * `relationship` * `networking`\",\n      \"type\": \"string\"\n     },\n     \"formattedValue\": {\n      \"description\": \"Output only. The value of the relationship interest translated and formatted in the viewer's account locale or the locale specified in the Accept-Language HTTP header.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"ContactGroupResponse\": {\n    \"description\": \"The response for a specific contact group.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"status\": {\n      \"$ref\": \"#/components/schemas/Status\"\n     },\n     \"contactGroup\": {\n      \"$ref\": \"#/components/schemas/ContactGroup\"\n     },\n     \"requestedResourceName\": {\n      \"description\": \"The original requested resource name.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"BatchGetContactGroupsResponse\": {\n    \"description\": \"The response to a batch get contact groups request.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"responses\": {\n      \"description\": \"The list of responses for each requested contact group resource.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/ContactGroupResponse\"\n      }\n     }\n    }\n   },\n   \"Address\": {\n    \"description\": \"A person's physical address. May be a P.O. box or street address. All fields are optional.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     },\n     \"type\": {\n      \"description\": \"The type of the address. The type can be custom or one of these predefined values: * `home` * `work` * `other`\",\n      \"type\": \"string\"\n     },\n     \"region\": {\n      \"description\": \"The region of the address; for example, the state or province.\",\n      \"type\": \"string\"\n     },\n     \"city\": {\n      \"description\": \"The city of the address.\",\n      \"type\": \"string\"\n     },\n     \"formattedValue\": {\n      \"description\": \"The unstructured value of the address. If this is not set by the user it will be automatically constructed from structured values.\",\n      \"type\": \"string\"\n     },\n     \"poBox\": {\n      \"description\": \"The P.O. box of the address.\",\n      \"type\": \"string\"\n     },\n     \"streetAddress\": {\n      \"description\": \"The street address.\",\n      \"type\": \"string\"\n     },\n     \"extendedAddress\": {\n      \"description\": \"The extended address of the address; for example, the apartment number.\",\n      \"type\": \"string\"\n     },\n     \"countryCode\": {\n      \"description\": \"The [ISO 3166-1 alpha-2](http://www.iso.org/iso/country_codes.htm) country code of the address.\",\n      \"type\": \"string\"\n     },\n     \"country\": {\n      \"description\": \"The country of the address.\",\n      \"type\": \"string\"\n     },\n     \"formattedType\": {\n      \"description\": \"Output only. The type of the address translated and formatted in the viewer's account locale or the `Accept-Language` HTTP header locale.\",\n      \"type\": \"string\"\n     },\n     \"postalCode\": {\n      \"description\": \"The postal code of the address.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"SipAddress\": {\n    \"description\": \"A person's SIP address. Session Initial Protocol addresses are used for VoIP communications to make voice or video calls over the internet.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     },\n     \"formattedType\": {\n      \"description\": \"Output only. The type of the SIP address translated and formatted in the viewer's account locale or the `Accept-Language` HTTP header locale.\",\n      \"type\": \"string\"\n     },\n     \"type\": {\n      \"description\": \"The type of the SIP address. The type can be custom or or one of these predefined values: * `home` * `work` * `mobile` * `other`\",\n      \"type\": \"string\"\n     },\n     \"value\": {\n      \"description\": \"The SIP address in the [RFC 3261 19.1](https://tools.ietf.org/html/rfc3261#section-19.1) SIP URI format.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"DomainMembership\": {\n    \"description\": \"A Google Workspace Domain membership.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"inViewerDomain\": {\n      \"description\": \"True if the person is in the viewer's Google Workspace domain.\",\n      \"type\": \"boolean\"\n     }\n    }\n   },\n   \"PersonMetadata\": {\n    \"description\": \"The metadata about a person.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"linkedPeopleResourceNames\": {\n      \"description\": \"Output only. Resource names of people linked to this resource.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"previousResourceNames\": {\n      \"description\": \"Output only. Any former resource names this person has had. Populated only for `people.connections.list` requests that include a sync token. The resource name may change when adding or removing fields that link a contact and profile such as a verified email, verified phone number, or profile URL.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"objectType\": {\n      \"description\": \"Output only. **DEPRECATED** (Please use `person.metadata.sources.profileMetadata.objectType` instead) The type of the person object.\",\n      \"type\": \"string\",\n      \"enum\": [\n       \"OBJECT_TYPE_UNSPECIFIED\",\n       \"PERSON\",\n       \"PAGE\"\n      ]\n     },\n     \"sources\": {\n      \"description\": \"The sources of data for the person.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Source\"\n      }\n     },\n     \"deleted\": {\n      \"description\": \"Output only. True if the person resource has been deleted. Populated only for `people.connections.list` and `otherContacts.list` sync requests.\",\n      \"type\": \"boolean\"\n     }\n    }\n   },\n   \"ContactGroupMetadata\": {\n    \"description\": \"The metadata about a contact group.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"updateTime\": {\n      \"description\": \"Output only. The time the group was last updated.\",\n      \"type\": \"string\",\n      \"format\": \"google-datetime\"\n     },\n     \"deleted\": {\n      \"description\": \"Output only. True if the contact group resource has been deleted. Populated only for [`ListContactGroups`](/people/api/rest/v1/contactgroups/list) requests that include a sync token.\",\n      \"type\": \"boolean\"\n     }\n    }\n   },\n   \"Person\": {\n    \"description\": \"Information about a person merged from various data sources such as the authenticated user's contacts and profile data. Most fields can have multiple items. The items in a field have no guaranteed order, but each non-empty field is guaranteed to have exactly one field with `metadata.primary` set to true.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"addresses\": {\n      \"description\": \"The person's street addresses.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Address\"\n      }\n     },\n     \"braggingRights\": {\n      \"description\": \"**DEPRECATED**: No data will be returned The person's bragging rights.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/BraggingRights\"\n      }\n     },\n     \"photos\": {\n      \"description\": \"Output only. The person's photos.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Photo\"\n      }\n     },\n     \"events\": {\n      \"description\": \"The person's events.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Event\"\n      }\n     },\n     \"skills\": {\n      \"description\": \"The person's skills.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Skill\"\n      }\n     },\n     \"sipAddresses\": {\n      \"description\": \"The person's SIP addresses.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/SipAddress\"\n      }\n     },\n     \"imClients\": {\n      \"description\": \"The person's instant messaging clients.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/ImClient\"\n      }\n     },\n     \"taglines\": {\n      \"description\": \"Output only. **DEPRECATED**: No data will be returned The person's taglines.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Tagline\"\n      }\n     },\n     \"genders\": {\n      \"description\": \"The person's genders. This field is a singleton for contact sources.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Gender\"\n      }\n     },\n     \"ageRange\": {\n      \"description\": \"Output only. **DEPRECATED** (Please use `person.ageRanges` instead) The person's age range.\",\n      \"type\": \"string\",\n      \"enum\": [\n       \"AGE_RANGE_UNSPECIFIED\",\n       \"LESS_THAN_EIGHTEEN\",\n       \"EIGHTEEN_TO_TWENTY\",\n       \"TWENTY_ONE_OR_OLDER\"\n      ]\n     },\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/PersonMetadata\"\n     },\n     \"nicknames\": {\n      \"description\": \"The person's nicknames.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Nickname\"\n      }\n     },\n     \"coverPhotos\": {\n      \"description\": \"Output only. The person's cover photos.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/CoverPhoto\"\n      }\n     },\n     \"relations\": {\n      \"description\": \"The person's relations.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Relation\"\n      }\n     },\n     \"miscKeywords\": {\n      \"description\": \"The person's miscellaneous keywords.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/MiscKeyword\"\n      }\n     },\n     \"emailAddresses\": {\n      \"description\": \"The person's email addresses. For `people.connections.list` and `otherContacts.list` the number of email addresses is limited to 100. If a Person has more email addresses the entire set can be obtained by calling GetPeople.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/EmailAddress\"\n      }\n     },\n     \"urls\": {\n      \"description\": \"The person's associated URLs.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Url\"\n      }\n     },\n     \"birthdays\": {\n      \"description\": \"The person's birthdays. This field is a singleton for contact sources.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Birthday\"\n      }\n     },\n     \"occupations\": {\n      \"description\": \"The person's occupations.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Occupation\"\n      }\n     },\n     \"ageRanges\": {\n      \"description\": \"Output only. The person's age ranges.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/AgeRangeType\"\n      }\n     },\n     \"clientData\": {\n      \"description\": \"The person's client data.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/ClientData\"\n      }\n     },\n     \"locales\": {\n      \"description\": \"The person's locale preferences.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Locale\"\n      }\n     },\n     \"organizations\": {\n      \"description\": \"The person's past or current organizations.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Organization\"\n      }\n     },\n     \"resourceName\": {\n      \"description\": \"The resource name for the person, assigned by the server. An ASCII string in the form of `people/{person_id}`.\",\n      \"type\": \"string\"\n     },\n     \"interests\": {\n      \"description\": \"The person's interests.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Interest\"\n      }\n     },\n     \"etag\": {\n      \"description\": \"The [HTTP entity tag](https://en.wikipedia.org/wiki/HTTP_ETag) of the resource. Used for web cache validation.\",\n      \"type\": \"string\"\n     },\n     \"names\": {\n      \"description\": \"The person's names. This field is a singleton for contact sources.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Name\"\n      }\n     },\n     \"biographies\": {\n      \"description\": \"The person's biographies. This field is a singleton for contact sources.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Biography\"\n      }\n     },\n     \"userDefined\": {\n      \"description\": \"The person's user defined data.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/UserDefined\"\n      }\n     },\n     \"phoneNumbers\": {\n      \"description\": \"The person's phone numbers. For `people.connections.list` and `otherContacts.list` the number of phone numbers is limited to 100. If a Person has more phone numbers the entire set can be obtained by calling GetPeople.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/PhoneNumber\"\n      }\n     },\n     \"externalIds\": {\n      \"description\": \"The person's external IDs.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/ExternalId\"\n      }\n     },\n     \"fileAses\": {\n      \"description\": \"The person's file-ases.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/FileAs\"\n      }\n     },\n     \"locations\": {\n      \"description\": \"The person's locations.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Location\"\n      }\n     },\n     \"memberships\": {\n      \"description\": \"The person's group memberships.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Membership\"\n      }\n     },\n     \"relationshipInterests\": {\n      \"description\": \"Output only. **DEPRECATED**: No data will be returned The person's relationship interests.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/RelationshipInterest\"\n      }\n     },\n     \"residences\": {\n      \"description\": \"**DEPRECATED**: (Please use `person.locations` instead) The person's residences.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Residence\"\n      }\n     },\n     \"calendarUrls\": {\n      \"description\": \"The person's calendar URLs.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/CalendarUrl\"\n      }\n     },\n     \"relationshipStatuses\": {\n      \"description\": \"Output only. **DEPRECATED**: No data will be returned The person's relationship statuses.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/RelationshipStatus\"\n      }\n     }\n    }\n   },\n   \"BatchUpdateContactsRequest\": {\n    \"description\": \"A request to update a batch of contacts.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"updateMask\": {\n      \"description\": \"Required. A field mask to restrict which fields on the person are updated. Multiple fields can be specified by separating them with commas. All specified fields will be replaced, or cleared if left empty for each person. Valid values are: * addresses * biographies * birthdays * calendarUrls * clientData * emailAddresses * events * externalIds * genders * imClients * interests * locales * locations * memberships * miscKeywords * names * nicknames * occupations * organizations * phoneNumbers * relations * sipAddresses * urls * userDefined\",\n      \"type\": \"string\",\n      \"format\": \"google-fieldmask\"\n     },\n     \"sources\": {\n      \"description\": \"Optional. A mask of what source types to return. Defaults to READ_SOURCE_TYPE_CONTACT and READ_SOURCE_TYPE_PROFILE if not set.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\",\n       \"enum\": [\n        \"READ_SOURCE_TYPE_UNSPECIFIED\",\n        \"READ_SOURCE_TYPE_PROFILE\",\n        \"READ_SOURCE_TYPE_CONTACT\",\n        \"READ_SOURCE_TYPE_DOMAIN_CONTACT\",\n        \"READ_SOURCE_TYPE_OTHER_CONTACT\"\n       ]\n      }\n     },\n     \"contacts\": {\n      \"description\": \"Required. A map of resource names to the person data to be updated. Allows up to 200 contacts in a single request.\",\n      \"type\": \"object\",\n      \"additionalProperties\": {\n       \"$ref\": \"#/components/schemas/Person\"\n      }\n     },\n     \"readMask\": {\n      \"description\": \"Required. A field mask to restrict which fields on each person are returned. Multiple fields can be specified by separating them with commas. If read mask is left empty, the post-mutate-get is skipped and no data will be returned in the response. Valid values are: * addresses * ageRanges * biographies * birthdays * calendarUrls * clientData * coverPhotos * emailAddresses * events * externalIds * genders * imClients * interests * locales * locations * memberships * metadata * miscKeywords * names * nicknames * occupations * organizations * phoneNumbers * photos * relations * sipAddresses * skills * urls * userDefined\",\n      \"type\": \"string\",\n      \"format\": \"google-fieldmask\"\n     }\n    }\n   },\n   \"BatchCreateContactsResponse\": {\n    \"description\": \"If not successful, returns BatchCreateContactsErrorDetails which contains a list of errors for each invalid contact. The response to a request to create a batch of contacts.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"createdPeople\": {\n      \"description\": \"The contacts that were created, unless the request `read_mask` is empty.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/PersonResponse\"\n      }\n     }\n    }\n   },\n   \"ListContactGroupsResponse\": {\n    \"description\": \"The response to a list contact groups request.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"totalItems\": {\n      \"description\": \"The total number of items in the list without pagination.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     },\n     \"nextPageToken\": {\n      \"description\": \"The token that can be used to retrieve the next page of results.\",\n      \"type\": \"string\"\n     },\n     \"nextSyncToken\": {\n      \"description\": \"The token that can be used to retrieve changes since the last request.\",\n      \"type\": \"string\"\n     },\n     \"contactGroups\": {\n      \"description\": \"The list of contact groups. Members of the contact groups are not populated.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/ContactGroup\"\n      }\n     }\n    }\n   },\n   \"PersonResponse\": {\n    \"description\": \"The response for a single person\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"person\": {\n      \"$ref\": \"#/components/schemas/Person\"\n     },\n     \"httpStatusCode\": {\n      \"description\": \"**DEPRECATED** (Please use status instead) [HTTP 1.1 status code] (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html).\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     },\n     \"status\": {\n      \"$ref\": \"#/components/schemas/Status\"\n     },\n     \"requestedResourceName\": {\n      \"description\": \"The original requested resource name. May be different than the resource name on the returned person. The resource name can change when adding or removing fields that link a contact and profile such as a verified email, verified phone number, or a profile URL.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"FieldMetadata\": {\n    \"description\": \"Metadata about a field.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"primary\": {\n      \"description\": \"Output only. True if the field is the primary field for all sources in the person. Each person will have at most one field with `primary` set to true.\",\n      \"type\": \"boolean\"\n     },\n     \"source\": {\n      \"$ref\": \"#/components/schemas/Source\"\n     },\n     \"verified\": {\n      \"description\": \"Output only. True if the field is verified; false if the field is unverified. A verified field is typically a name, email address, phone number, or website that has been confirmed to be owned by the person.\",\n      \"type\": \"boolean\"\n     },\n     \"sourcePrimary\": {\n      \"description\": \"True if the field is the primary field for the source. Each source must have at most one field with `source_primary` set to true.\",\n      \"type\": \"boolean\"\n     }\n    }\n   },\n   \"UpdateContactPhotoResponse\": {\n    \"description\": \"The response for updating a contact's photo.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"person\": {\n      \"$ref\": \"#/components/schemas/Person\"\n     }\n    }\n   },\n   \"Interest\": {\n    \"description\": \"One of the person's interests.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"value\": {\n      \"description\": \"The interest; for example, `stargazing`.\",\n      \"type\": \"string\"\n     },\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     }\n    }\n   },\n   \"Event\": {\n    \"description\": \"An event related to the person.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"type\": {\n      \"description\": \"The type of the event. The type can be custom or one of these predefined values: * `anniversary` * `other`\",\n      \"type\": \"string\"\n     },\n     \"formattedType\": {\n      \"description\": \"Output only. The type of the event translated and formatted in the viewer's account locale or the `Accept-Language` HTTP header locale.\",\n      \"type\": \"string\"\n     },\n     \"date\": {\n      \"$ref\": \"#/components/schemas/Date\"\n     },\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     }\n    }\n   },\n   \"Url\": {\n    \"description\": \"A person's associated URLs.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"formattedType\": {\n      \"description\": \"Output only. The type of the URL translated and formatted in the viewer's account locale or the `Accept-Language` HTTP header locale.\",\n      \"type\": \"string\"\n     },\n     \"metadata\": {\n      \"$ref\": \"#/components/schemas/FieldMetadata\"\n     },\n     \"type\": {\n      \"description\": \"The type of the URL. The type can be custom or one of these predefined values: * `home` * `work` * `blog` * `profile` * `homePage` * `ftp` * `reservations` * `appInstallPage`: website for a Currents application. * `other`\",\n      \"type\": \"string\"\n     },\n     \"value\": {\n      \"description\": \"The URL.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"GroupClientData\": {\n    \"description\": \"Arbitrary client data that is populated by clients. Duplicate keys and values are allowed.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"key\": {\n      \"description\": \"The client specified key of the client data.\",\n      \"type\": \"string\"\n     },\n     \"value\": {\n      \"description\": \"The client specified value of the client data.\",\n      \"type\": \"string\"\n     }\n    }\n   }\n  },\n  \"securitySchemes\": {\n   \"bearer\": {\n    \"type\": \"http\",\n    \"scheme\": \"bearer\"\n   }\n  }\n }\n}\n"},{"path":"products/contacts/openapi.ts","content":"// Generated by scripts/google-vendor.ts from packages/google-contacts; edit the original and rerun it.\n// openapi.json is generated from Google's official People API v1 Discovery document\n// (https://people.googleapis.com/$discovery/rest?version=v1, revision 20261007) by\n// discovery-to-openapi.mjs; see README. Every operation takes one OAuth bearer token.\nimport type { JsonObject } from \"apps\";\nimport type { OpenapiToolNamesOptions } from \"apps/openapi\";\nimport document from \"./openapi.json\" with { type: \"json\" };\n\n// The inferred JSON type has no index signature, so widen it once here.\nconst widen = (value: unknown): JsonObject => JSON.parse(JSON.stringify(value));\n\nexport const options = {\n  source: { document: widen(document) },\n  allowedOrigin: \"https://people.googleapis.com\",\n  securitySchemes: { bearer: { type: \"http\", scheme: \"bearer\" } },\n  methods: {\n    oauth: [{ scheme: \"bearer\", field: \"access_token\", part: \"value\", prefix: \"\" }],\n  },\n  oauth: [],\n} satisfies OpenapiToolNamesOptions;\n"},{"path":"products/docs/tools.ts","content":"// Generated by scripts/google-vendor.ts from packages/google-docs; edit the original and rerun it.\n// The tools, without the account: index.ts and packages/google (through scripts/google-vendor.ts) both mount them.\nimport {\n  array,\n  boolean,\n  decodeJson,\n  json,\n  mutation,\n  number,\n  object,\n  query,\n  router,\n  string,\n} from \"apps\";\n\nconst base = \"https://docs.googleapis.com/v1/documents\";\n\n/** The router's metadata, shared with packages/google. */\nexport const meta = {\n  title: \"Google Docs\",\n  description:\n    \"Read Google Docs as JSON or plain text, create documents, and edit them: insert, replace and delete text, styles, lists, tables, images and raw batchUpdate requests.\",\n  instructions:\n    \"Indexes are UTF-16 code units; the body starts at 1. Call getText or getDocument first to find indexes. Within one batchUpdate, requests apply in order, so edit later positions first. Pass requiredRevisionId (from getDocument) to fail instead of overwriting concurrent edits.\",\n};\n\ntype Fetch = typeof fetch;\n\nconst Location = { index: number(), tabId: string().optional() };\nconst Range = { startIndex: number(), endIndex: number(), tabId: string().optional() };\nconst documentId = string({ minLength: 1 });\n\nexport function tools(token: string, fetcher: Fetch, signal: AbortSignal | undefined) {\n  const call = async (path: string, init: { method?: string; body?: unknown; search?: Record<string, string | undefined> } = {}) => {\n    const url = new URL(`${base}${path}`);\n    for (const [key, value] of Object.entries(init.search ?? {})) if (value !== undefined) url.searchParams.set(key, value);\n    const response = await fetcher(url.toString(), {\n      method: init.method ?? \"GET\",\n      signal,\n      headers: { Authorization: `Bearer ${token}`, \"content-type\": \"application/json\" },\n      body: init.body === undefined ? undefined : JSON.stringify(init.body),\n    });\n    return decodeJson(response, json());\n  };\n  const batch = (id: string, requests: unknown[], requiredRevisionId?: string) =>\n    call(`/${encodeURIComponent(id)}:batchUpdate`, {\n      method: \"POST\",\n      body: { requests, ...(requiredRevisionId ? { writeControl: { requiredRevisionId } } : {}) },\n    });\n  const revision = string().optional();\n\n  return router({\n    getDocument: query(\n      {\n        description:\n          \"Get a document as Google Docs JSON: title, revisionId, body structure with character indexes, styles, lists, named ranges.\",\n        input: object({\n          documentId,\n          includeTabsContent: boolean().optional(),\n          suggestionsViewMode: string().optional(),\n        }),\n      },\n      async (_ctx, { documentId, includeTabsContent, suggestionsViewMode }) =>\n        call(`/${encodeURIComponent(documentId)}`, {\n          search: { includeTabsContent: includeTabsContent === undefined ? undefined : String(includeTabsContent), suggestionsViewMode },\n        }),\n    ),\n    getText: query(\n      {\n        description:\n          \"Get the plain text of a document's body, with the start index of each paragraph so edits can target it.\",\n        input: object({ documentId, tabId: string().optional() }),\n      },\n      async (_ctx, { documentId, tabId }) => {\n        const doc = (await call(`/${encodeURIComponent(documentId)}`, {\n          search: { includeTabsContent: tabId ? \"true\" : undefined },\n        })) as Record<string, any>;\n        const tab = tabId ? findTab(doc.tabs ?? [], tabId) : undefined;\n        if (tabId && !tab) throw new Error(`Tab ${tabId} was not found in document ${documentId}`);\n        const content = (tab?.documentTab ?? doc).body?.content ?? [];\n        const paragraphs: { startIndex: number; text: string }[] = [];\n        collect(content, paragraphs);\n        return {\n          title: doc.title ?? \"\",\n          revisionId: doc.revisionId ?? null,\n          text: paragraphs.map((p) => p.text).join(\"\"),\n          paragraphs,\n        };\n      },\n    ),\n    createDocument: mutation(\n      {\n        description: \"Create a blank document with the given title. Returns the new document including its documentId.\",\n        input: object({ title: string() }),\n      },\n      async (_ctx, { title }) => call(\"\", { method: \"POST\", body: { title } }),\n    ),\n    batchUpdate: mutation(\n      {\n        description:\n          \"Apply raw documents.batchUpdate requests (an array of Request objects, e.g. insertText, updateTextStyle). Indexes refer to the document before the batch; requests apply in order, so edit from the end of the document backwards. Use for anything the other tools do not cover.\",\n        input: object({ documentId, requests: array(json()), requiredRevisionId: revision }),\n      },\n      async (_ctx, { documentId, requests, requiredRevisionId }) => batch(documentId, [...requests], requiredRevisionId),\n    ),\n    appendText: mutation(\n      {\n        description: \"Append text at the end of the document body (or of a tab).\",\n        input: object({ documentId, text: string(), tabId: string().optional() }),\n      },\n      async (_ctx, { documentId, text, tabId }) =>\n        batch(documentId, [{ insertText: { text, endOfSegmentLocation: tabId ? { tabId } : {} } }]),\n    ),\n    insertText: mutation(\n      {\n        description: \"Insert text at a character index (1 is the start of the body).\",\n        input: object({ documentId, text: string(), ...Location, requiredRevisionId: revision }),\n      },\n      async (_ctx, { documentId, text, index, tabId, requiredRevisionId }) =>\n        batch(documentId, [{ insertText: { text, location: { index, ...(tabId ? { tabId } : {}) } } }], requiredRevisionId),\n    ),\n    replaceAllText: mutation(\n      {\n        description: \"Replace every occurrence of a string in the document.\",\n        input: object({\n          documentId,\n          find: string({ minLength: 1 }),\n          replaceWith: string(),\n          matchCase: boolean().optional(),\n        }),\n      },\n      async (_ctx, { documentId, find, replaceWith, matchCase }) =>\n        batch(documentId, [\n          { replaceAllText: { containsText: { text: find, matchCase: matchCase ?? false }, replaceText: replaceWith } },\n        ]),\n    ),\n    deleteContentRange: mutation(\n      {\n        description: \"Delete the content between startIndex (inclusive) and endIndex (exclusive).\",\n        input: object({ documentId, ...Range, requiredRevisionId: revision }),\n      },\n      async (_ctx, { documentId, startIndex, endIndex, tabId, requiredRevisionId }) =>\n        batch(documentId, [{ deleteContentRange: { range: { startIndex, endIndex, ...(tabId ? { tabId } : {}) } } }], requiredRevisionId),\n    ),\n    updateTextStyle: mutation(\n      {\n        description:\n          \"Style a text range. textStyle is a Docs TextStyle object (bold, italic, underline, strikethrough, fontSize, foregroundColor, link, ...); fields is the field mask naming which to set, e.g. \\\"bold,italic\\\".\",\n        input: object({ documentId, ...Range, textStyle: json(), fields: string({ minLength: 1 }) }),\n      },\n      async (_ctx, { documentId, startIndex, endIndex, tabId, textStyle, fields }) =>\n        batch(documentId, [\n          { updateTextStyle: { range: { startIndex, endIndex, ...(tabId ? { tabId } : {}) }, textStyle, fields } },\n        ]),\n    ),\n    updateParagraphStyle: mutation(\n      {\n        description:\n          \"Style the paragraphs in a range. paragraphStyle is a Docs ParagraphStyle (namedStyleType such as HEADING_1, alignment, lineSpacing, ...); fields is the field mask.\",\n        input: object({ documentId, ...Range, paragraphStyle: json(), fields: string({ minLength: 1 }) }),\n      },\n      async (_ctx, { documentId, startIndex, endIndex, tabId, paragraphStyle, fields }) =>\n        batch(documentId, [\n          { updateParagraphStyle: { range: { startIndex, endIndex, ...(tabId ? { tabId } : {}) }, paragraphStyle, fields } },\n        ]),\n    ),\n    createParagraphBullets: mutation(\n      {\n        description: \"Turn the paragraphs in a range into a bulleted or numbered list.\",\n        input: object({ documentId, ...Range, bulletPreset: string().default(\"BULLET_DISC_CIRCLE_SQUARE\") }),\n      },\n      async (_ctx, { documentId, startIndex, endIndex, tabId, bulletPreset }) =>\n        batch(documentId, [\n          { createParagraphBullets: { range: { startIndex, endIndex, ...(tabId ? { tabId } : {}) }, bulletPreset } },\n        ]),\n    ),\n    insertTable: mutation(\n      {\n        description: \"Insert an empty table at an index.\",\n        input: object({ documentId, rows: number(), columns: number(), ...Location }),\n      },\n      async (_ctx, { documentId, rows, columns, index, tabId }) =>\n        batch(documentId, [{ insertTable: { rows, columns, location: { index, ...(tabId ? { tabId } : {}) } } }]),\n    ),\n    insertInlineImage: mutation(\n      {\n        description: \"Insert an image from a public URL at an index.\",\n        input: object({\n          documentId,\n          uri: string({ minLength: 1 }),\n          ...Location,\n          widthPt: number().optional(),\n          heightPt: number().optional(),\n        }),\n      },\n      async (_ctx, { documentId, uri, index, tabId, widthPt, heightPt }) => {\n        if ((widthPt === undefined) !== (heightPt === undefined)) {\n          throw new Error(\"Provide widthPt and heightPt together, or neither\");\n        }\n        if ((widthPt !== undefined && widthPt <= 0) || (heightPt !== undefined && heightPt <= 0)) {\n          throw new Error(\"widthPt and heightPt must be positive\");\n        }\n        return batch(documentId, [\n          {\n            insertInlineImage: {\n              uri,\n              location: { index, ...(tabId ? { tabId } : {}) },\n              ...(widthPt !== undefined && heightPt !== undefined\n                ? { objectSize: { width: { magnitude: widthPt, unit: \"PT\" }, height: { magnitude: heightPt, unit: \"PT\" } } }\n                : {}),\n            },\n          },\n        ]);\n      },\n    ),\n    insertPageBreak: mutation(\n      {\n        description: \"Insert a page break at an index.\",\n        input: object({ documentId, ...Location }),\n      },\n      async (_ctx, { documentId, index, tabId }) =>\n        batch(documentId, [{ insertPageBreak: { location: { index, ...(tabId ? { tabId } : {}) } } }]),\n    ),\n    createNamedRange: mutation(\n      {\n        description: \"Give a text range a name so it can be found again after edits.\",\n        input: object({ documentId, name: string({ minLength: 1 }), ...Range }),\n      },\n      async (_ctx, { documentId, name, startIndex, endIndex, tabId }) =>\n        batch(documentId, [{ createNamedRange: { name, range: { startIndex, endIndex, ...(tabId ? { tabId } : {}) } } }]),\n    ),\n    deleteNamedRange: mutation(\n      {\n        description: \"Delete named ranges by name (all with that name) or by id.\",\n        input: object({ documentId, name: string().optional(), namedRangeId: string().optional() }),\n      },\n      async (_ctx, { documentId, name, namedRangeId }) => {\n        if ((name === undefined) === (namedRangeId === undefined)) {\n          throw new Error(\"Provide exactly one of name or namedRangeId\");\n        }\n        return batch(documentId, [{ deleteNamedRange: namedRangeId !== undefined ? { namedRangeId } : { name } }]);\n      },\n    ),\n    replaceNamedRangeContent: mutation(\n      {\n        description: \"Replace the content of every range with the given name.\",\n        input: object({ documentId, name: string({ minLength: 1 }), text: string() }),\n      },\n      async (_ctx, { documentId, name, text }) =>\n        batch(documentId, [{ replaceNamedRangeContent: { namedRangeName: name, text } }]),\n    ),\n  });\n}\n\nfunction findTab(tabs: any[], id: string): any {\n  for (const tab of tabs) {\n    if (tab.tabProperties?.tabId === id) return tab;\n    const child = findTab(tab.childTabs ?? [], id);\n    if (child) return child;\n  }\n  return undefined;\n}\n\nfunction collect(content: any[], out: { startIndex: number; text: string }[]) {\n  for (const element of content) {\n    if (element.paragraph) {\n      const text = (element.paragraph.elements ?? []).map((e: any) => e.textRun?.content ?? \"\").join(\"\");\n      out.push({ startIndex: element.startIndex ?? 0, text });\n    } else if (element.table) {\n      for (const row of element.table.tableRows ?? [])\n        for (const cell of row.tableCells ?? []) collect(cell.content ?? [], out);\n    } else if (element.tableOfContents) {\n      collect(element.tableOfContents.content ?? [], out);\n    }\n  }\n}\n"},{"path":"products/drive/drive-openapi.json","content":"{\n \"openapi\": \"3.0.3\",\n \"info\": {\n  \"title\": \"Google Drive API\",\n  \"version\": \"v3 (discovery revision 20261005)\",\n  \"description\": \"The Google Drive API allows clients to access resources from Google Drive.\"\n },\n \"servers\": [\n  {\n   \"url\": \"https://www.googleapis.com/drive/v3\"\n  }\n ],\n \"security\": [\n  {\n   \"bearer\": []\n  }\n ],\n \"paths\": {\n  \"/about\": {\n   \"get\": {\n    \"operationId\": \"drive.about.get\",\n    \"description\": \"Gets information about the user, the user's Drive, and system capabilities. For more information, see [Return user info](https://developers.google.com/workspace/drive/api/guides/user-info). Required: The `fields` parameter must be set. To return the exact fields you need, see [Return specific fields](https://developers.google.com/workspace/drive/api/guides/fields-parameter).\",\n    \"parameters\": [\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/About\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/operations/{name}\": {\n   \"get\": {\n    \"operationId\": \"drive.operations.get\",\n    \"description\": \"Gets the latest state of a long-running operation. Clients can use this method to poll the operation result at intervals as recommended by the API service.\",\n    \"parameters\": [\n     {\n      \"name\": \"name\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The name of the operation resource.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Operation\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/channels/stop\": {\n   \"post\": {\n    \"operationId\": \"drive.channels.stop\",\n    \"description\": \"Stops watching resources through this channel. For more information, see [Notifications for resource changes](https://developers.google.com/workspace/drive/api/guides/push).\",\n    \"parameters\": [\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\"\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Channel\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/apps\": {\n   \"get\": {\n    \"operationId\": \"drive.apps.list\",\n    \"description\": \"Lists a user's installed apps. For more information, see [Return user info](https://developers.google.com/workspace/drive/api/guides/user-info).\",\n    \"parameters\": [\n     {\n      \"name\": \"appFilterExtensions\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"A comma-separated list of file extensions to limit returned results. All results within the given app query scope which can open any of the given file extensions are included in the response. If `appFilterMimeTypes` are provided as well, the result is a union of the two resulting app lists.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"appFilterMimeTypes\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"A comma-separated list of file extensions to limit returned results. All results within the given app query scope which can open any of the given MIME types will be included in the response. If `appFilterExtensions` are provided as well, the result is a union of the two resulting app lists.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"languageCode\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"A language or locale code, as defined by BCP 47, with some extensions from Unicode's LDML format (http://www.unicode.org/reports/tr35/).\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/AppList\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/apps/{appId}\": {\n   \"get\": {\n    \"operationId\": \"drive.apps.get\",\n    \"description\": \"Gets a specific app. For more information, see [Return user info](https://developers.google.com/workspace/drive/api/guides/user-info).\",\n    \"parameters\": [\n     {\n      \"name\": \"appId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the app.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/App\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/changes/watch\": {\n   \"post\": {\n    \"operationId\": \"drive.changes.watch\",\n    \"description\": \"Subscribes to changes for a user. For more information, see [Notifications for resource changes](https://developers.google.com/workspace/drive/api/guides/push).\",\n    \"parameters\": [\n     {\n      \"name\": \"includeRemoved\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to include changes indicating that items have been removed from the list of changes, for example by deletion or loss of access.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": true,\n      \"description\": \"The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response or to the response from the getStartPageToken method.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"supportsTeamDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: Use `supportsAllDrives` instead.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"driveId\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The shared drive from which changes will be returned. If specified the change IDs will be reflective of the shared drive; use the combined drive ID and change ID as an identifier.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"pageSize\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The maximum number of changes to return. The service may return fewer than this value. If unspecified, at most 100 changes will be returned. The maximum value is 1000; values above 1000 will be coerced to 1000.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"includePermissionsForView\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Specifies which additional view's permissions to include in the response. Only 'published' is supported.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"restrictToMyDrive\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to restrict the results to changes inside the My Drive hierarchy. This omits changes to files such as those in the Application Data folder or shared files which have not been added to My Drive.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"supportsAllDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether the requesting application supports both My Drives and shared drives.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"teamDriveId\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: Use `driveId` instead.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"includeLabels\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"A comma-separated list of IDs of labels to include in the `labelInfo` part of the response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"includeTeamDriveItems\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: Use `includeItemsFromAllDrives` instead.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"includeCorpusRemovals\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether changes should include the file resource if the file is still accessible by the user at the time of the request, even when a file was removed from the list of changes and there will be no further change entries for this file.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"spaces\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"A comma-separated list of spaces to query within the corpora. Supported values are 'drive' and 'appDataFolder'.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"includeItemsFromAllDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether both My Drive and shared drive items should be included in results.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Channel\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Channel\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/changes/startPageToken\": {\n   \"get\": {\n    \"operationId\": \"drive.changes.getStartPageToken\",\n    \"description\": \"Gets the starting pageToken for listing future changes. For more information, see [Retrieve changes](https://developers.google.com/workspace/drive/api/guides/manage-changes).\",\n    \"parameters\": [\n     {\n      \"name\": \"teamDriveId\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: Use `driveId` instead.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"driveId\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The ID of the shared drive for which the starting pageToken for listing future changes from that shared drive will be returned.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"supportsTeamDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: Use `supportsAllDrives` instead.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"supportsAllDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether the requesting application supports both My Drives and shared drives.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/StartPageToken\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/changes\": {\n   \"get\": {\n    \"operationId\": \"drive.changes.list\",\n    \"description\": \"Lists the changes for a user or shared drive. For more information, see [Retrieve changes](https://developers.google.com/workspace/drive/api/guides/manage-changes).\",\n    \"parameters\": [\n     {\n      \"name\": \"spaces\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"A comma-separated list of spaces to query within the corpora. Supported values are 'drive' and 'appDataFolder'.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"supportsTeamDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: Use `supportsAllDrives` instead.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"includeItemsFromAllDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether both My Drive and shared drive items should be included in results.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"includeTeamDriveItems\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: Use `includeItemsFromAllDrives` instead.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"includeCorpusRemovals\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether changes should include the file resource if the file is still accessible by the user at the time of the request, even when a file was removed from the list of changes and there will be no further change entries for this file.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"supportsAllDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether the requesting application supports both My Drives and shared drives.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"restrictToMyDrive\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to restrict the results to changes inside the My Drive hierarchy. This omits changes to files such as those in the Application Data folder or shared files which have not been added to My Drive.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"includePermissionsForView\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Specifies which additional view's permissions to include in the response. Only 'published' is supported.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"includeLabels\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"A comma-separated list of IDs of labels to include in the `labelInfo` part of the response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"driveId\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The shared drive from which changes will be returned. If specified the change IDs will be reflective of the shared drive; use the combined drive ID and change ID as an identifier.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": true,\n      \"description\": \"The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response or to the response from the getStartPageToken method.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"pageSize\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The maximum number of changes to return. The service may return fewer than this value. If unspecified, at most 100 changes will be returned. The maximum value is 1000; values above 1000 will be coerced to 1000.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"includeRemoved\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to include changes indicating that items have been removed from the list of changes, for example by deletion or loss of access.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"teamDriveId\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: Use `driveId` instead.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/ChangeList\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/drives/{driveId}\": {\n   \"patch\": {\n    \"operationId\": \"drive.drives.update\",\n    \"description\": \"Updates the metadata for a shared drive. For more information, see [Manage shared drives](https://developers.google.com/workspace/drive/api/guides/manage-shareddrives).\",\n    \"parameters\": [\n     {\n      \"name\": \"useDomainAdminAccess\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Issue the request as a domain administrator; if set to true, then the requester will be granted access if they are an administrator of the domain to which the shared drive belongs.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"driveId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the shared drive.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Drive\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Drive\"\n       }\n      }\n     }\n    }\n   },\n   \"get\": {\n    \"operationId\": \"drive.drives.get\",\n    \"description\": \"Gets a shared drive's metadata by ID. For more information, see [Manage shared drives](https://developers.google.com/workspace/drive/api/guides/manage-shareddrives).\",\n    \"parameters\": [\n     {\n      \"name\": \"driveId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the shared drive.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"useDomainAdminAccess\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Issue the request as a domain administrator; if set to true, then the requester will be granted access if they are an administrator of the domain to which the shared drive belongs.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Drive\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   },\n   \"delete\": {\n    \"operationId\": \"drive.drives.delete\",\n    \"description\": \"Permanently deletes a shared drive for which the user is an `organizer`. The shared drive cannot contain any untrashed items. For more information, see [Manage shared drives](https://developers.google.com/workspace/drive/api/guides/manage-shareddrives).\",\n    \"parameters\": [\n     {\n      \"name\": \"useDomainAdminAccess\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Issue the request as a domain administrator; if set to true, then the requester will be granted access if they are an administrator of the domain to which the shared drive belongs.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"driveId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the shared drive.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"allowItemDeletion\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether any items inside the shared drive should also be deleted. This option is only supported when `useDomainAdminAccess` is also set to `true`.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\"\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/drives\": {\n   \"get\": {\n    \"operationId\": \"drive.drives.list\",\n    \"description\": \"Lists the user's shared drives. This method accepts the `q` parameter, which is a search query combining one or more search terms. For more information, see the [Search for shared drives](https://developers.google.com/workspace/drive/api/guides/search-shareddrives) guide.\",\n    \"parameters\": [\n     {\n      \"name\": \"pageSize\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The maximum number of shared drives to return. The service may return fewer than this value. If unspecified, at most 10 shared drives will be returned. The maximum value is 100; values above 100 will be coerced to 100.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"useDomainAdminAccess\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Issue the request as a domain administrator; if set to true, then all shared drives of the domain in which the requester is an administrator are returned.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Page token for shared drives.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"q\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Query string for searching shared drives.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/DriveList\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   },\n   \"post\": {\n    \"operationId\": \"drive.drives.create\",\n    \"description\": \"Creates a shared drive. For more information, see [Manage shared drives](https://developers.google.com/workspace/drive/api/guides/manage-shareddrives).\",\n    \"parameters\": [\n     {\n      \"name\": \"requestId\",\n      \"in\": \"query\",\n      \"required\": true,\n      \"description\": \"Required. An ID, such as a random UUID, which uniquely identifies this user's request for idempotent creation of a shared drive. A repeated request by the same user and with the same request ID will avoid creating duplicates by attempting to create the same shared drive. If the shared drive already exists a 409 error will be returned.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Drive\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Drive\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/drives/{driveId}/hide\": {\n   \"post\": {\n    \"operationId\": \"drive.drives.hide\",\n    \"description\": \"Hides a shared drive from the default view. For more information, see [Manage shared drives](https://developers.google.com/workspace/drive/api/guides/manage-shareddrives).\",\n    \"parameters\": [\n     {\n      \"name\": \"driveId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the shared drive.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Drive\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/drives/{driveId}/unhide\": {\n   \"post\": {\n    \"operationId\": \"drive.drives.unhide\",\n    \"description\": \"Restores a shared drive to the default view. For more information, see [Manage shared drives](https://developers.google.com/workspace/drive/api/guides/manage-shareddrives).\",\n    \"parameters\": [\n     {\n      \"name\": \"driveId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the shared drive.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Drive\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/files/{fileId}/permissions\": {\n   \"post\": {\n    \"operationId\": \"drive.permissions.create\",\n    \"description\": \"Creates a permission for a file or shared drive. For more information, see [Share files, folders, and drives](https://developers.google.com/workspace/drive/api/guides/manage-sharing). **Warning:** Concurrent permission modifications (such as update or delete) on the same file, folder, or shared drive aren't supported across any users or clients; only the last update is applied.\",\n    \"parameters\": [\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file or shared drive.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"useDomainAdminAccess\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Issue the request as a domain administrator. If set to `true`, and if the following additional conditions are met, the requester is granted access: 1. The file ID parameter refers to a shared drive. 2. The requester is an administrator of the domain to which the shared drive belongs. For more information, see [Manage shared drives as domain administrators](https://developers.google.com/workspace/drive/api/guides/manage-shareddrives#manage-administrators).\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"enforceExpansiveAccess\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: All requests use the expansive access rules.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"emailMessage\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"A plain text custom message to include in the notification email.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"supportsTeamDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: Use `supportsAllDrives` instead.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"supportsAllDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether the requesting application supports both My Drives and shared drives.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"enforceSingleParent\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: See `moveToNewOwnersRoot` for details.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"moveToNewOwnersRoot\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"This parameter only takes effect if the item isn't in a shared drive and the request is attempting to transfer the ownership of the item. If set to `true`, the item is moved to the new owner's My Drive root folder and all prior parents removed. If set to `false`, parents aren't changed.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"sendNotificationEmail\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to send a notification email when sharing to users or groups. This defaults to `true` for users and groups, and is not allowed for other requests. It must not be disabled for ownership transfers.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"transferOwnership\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to transfer ownership to the specified user and downgrade the current owner to a writer. This parameter is required as an acknowledgement of the side effect. For more information, see [Transfer file ownership](https://developers.google.com/workspace/drive/api/guides/transfer-file).\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Permission\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Permission\"\n       }\n      }\n     }\n    }\n   },\n   \"get\": {\n    \"operationId\": \"drive.permissions.list\",\n    \"description\": \"Lists a file's or shared drive's permissions. For more information, see [Share files, folders, and drives](https://developers.google.com/workspace/drive/api/guides/manage-sharing).\",\n    \"parameters\": [\n     {\n      \"name\": \"supportsTeamDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: Use `supportsAllDrives` instead.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file or shared drive.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"includePermissionsForView\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Specifies which additional view's permissions to include in the response. Only `published` is supported.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The token for continuing a previous list request on the next page. This should be set to the value of `nextPageToken` from the previous response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"pageSize\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The maximum number of permissions to return. The service may return fewer than this value. If unspecified, at most 100 permissions will be returned for shared drives, and the entire list of permissions for non-shared drives. The maximum value is 100; values above 100 will be coerced to 100.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"supportsAllDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether the requesting application supports both My Drives and shared drives.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"useDomainAdminAccess\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Issue the request as a domain administrator. If set to `true`, and if the following additional conditions are met, the requester is granted access: 1. The file ID parameter refers to a shared drive. 2. The requester is an administrator of the domain to which the shared drive belongs. For more information, see [Manage shared drives as domain administrators](https://developers.google.com/workspace/drive/api/guides/manage-shareddrives#manage-administrators).\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/PermissionList\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/files/{fileId}/permissions/{permissionId}\": {\n   \"get\": {\n    \"operationId\": \"drive.permissions.get\",\n    \"description\": \"Gets a permission by ID. For more information, see [Share files, folders, and drives](https://developers.google.com/workspace/drive/api/guides/manage-sharing).\",\n    \"parameters\": [\n     {\n      \"name\": \"supportsAllDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether the requesting application supports both My Drives and shared drives.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"permissionId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the permission.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"supportsTeamDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: Use `supportsAllDrives` instead.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"useDomainAdminAccess\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Issue the request as a domain administrator. If set to `true`, and if the following additional conditions are met, the requester is granted access: 1. The file ID parameter refers to a shared drive. 2. The requester is an administrator of the domain to which the shared drive belongs. For more information, see [Manage shared drives as domain administrators](https://developers.google.com/workspace/drive/api/guides/manage-shareddrives#manage-administrators).\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Permission\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   },\n   \"delete\": {\n    \"operationId\": \"drive.permissions.delete\",\n    \"description\": \"Deletes a permission. For more information, see [Share files, folders, and drives](https://developers.google.com/workspace/drive/api/guides/manage-sharing). **Warning:** Concurrent permission modifications (such as update or delete) on the same file, folder, or shared drive aren't supported across any users or clients; only the last update is applied.\",\n    \"parameters\": [\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file or shared drive.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"permissionId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the permission.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"supportsTeamDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: Use `supportsAllDrives` instead.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"supportsAllDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether the requesting application supports both My Drives and shared drives.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"enforceExpansiveAccess\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: All requests use the expansive access rules.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"useDomainAdminAccess\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Issue the request as a domain administrator. If set to `true`, and if the following additional conditions are met, the requester is granted access: 1. The file ID parameter refers to a shared drive. 2. The requester is an administrator of the domain to which the shared drive belongs. For more information, see [Manage shared drives as domain administrators](https://developers.google.com/workspace/drive/api/guides/manage-shareddrives#manage-administrators).\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\"\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   },\n   \"patch\": {\n    \"operationId\": \"drive.permissions.update\",\n    \"description\": \"Updates a permission with patch semantics. For more information, see [Share files, folders, and drives](https://developers.google.com/workspace/drive/api/guides/manage-sharing). **Warning:** Concurrent permission modifications (such as update or delete) on the same file, folder, or shared drive aren't supported across any users or clients; only the last update is applied.\",\n    \"parameters\": [\n     {\n      \"name\": \"useDomainAdminAccess\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Issue the request as a domain administrator. If set to `true`, and if the following additional conditions are met, the requester is granted access: 1. The file ID parameter refers to a shared drive. 2. The requester is an administrator of the domain to which the shared drive belongs. For more information, see [Manage shared drives as domain administrators](https://developers.google.com/workspace/drive/api/guides/manage-shareddrives#manage-administrators).\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"enforceExpansiveAccess\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: All requests use the expansive access rules.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"transferOwnership\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to transfer ownership to the specified user and downgrade the current owner to a writer. This parameter is required as an acknowledgement of the side effect. For more information, see [Transfer file ownership](https://developers.google.com//workspace/drive/api/guides/transfer-file).\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"removeExpiration\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to remove the expiration date.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"supportsAllDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether the requesting application supports both My Drives and shared drives.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"permissionId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the permission.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file or shared drive.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"supportsTeamDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: Use `supportsAllDrives` instead.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Permission\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Permission\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/teamdrives/{teamDriveId}\": {\n   \"get\": {\n    \"operationId\": \"drive.teamdrives.get\",\n    \"description\": \"Deprecated: Use `drives.get` instead.\",\n    \"parameters\": [\n     {\n      \"name\": \"teamDriveId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the Team Drive\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"useDomainAdminAccess\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Issue the request as a domain administrator; if set to true, then the requester will be granted access if they are an administrator of the domain to which the Team Drive belongs.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/TeamDrive\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   },\n   \"delete\": {\n    \"operationId\": \"drive.teamdrives.delete\",\n    \"description\": \"Deprecated: Use `drives.delete` instead.\",\n    \"parameters\": [\n     {\n      \"name\": \"teamDriveId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the Team Drive\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\"\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   },\n   \"patch\": {\n    \"operationId\": \"drive.teamdrives.update\",\n    \"description\": \"Deprecated: Use `drives.update` instead.\",\n    \"parameters\": [\n     {\n      \"name\": \"useDomainAdminAccess\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Issue the request as a domain administrator; if set to true, then the requester will be granted access if they are an administrator of the domain to which the Team Drive belongs.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"teamDriveId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the Team Drive\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/TeamDrive\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/TeamDrive\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/teamdrives\": {\n   \"post\": {\n    \"operationId\": \"drive.teamdrives.create\",\n    \"description\": \"Deprecated: Use `drives.create` instead.\",\n    \"parameters\": [\n     {\n      \"name\": \"requestId\",\n      \"in\": \"query\",\n      \"required\": true,\n      \"description\": \"Required. An ID, such as a random UUID, which uniquely identifies this user's request for idempotent creation of a Team Drive. A repeated request by the same user and with the same request ID will avoid creating duplicates by attempting to create the same Team Drive. If the Team Drive already exists a 409 error will be returned.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/TeamDrive\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/TeamDrive\"\n       }\n      }\n     }\n    }\n   },\n   \"get\": {\n    \"operationId\": \"drive.teamdrives.list\",\n    \"description\": \"Deprecated: Use `drives.list` instead.\",\n    \"parameters\": [\n     {\n      \"name\": \"q\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Query string for searching Team Drives.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"pageSize\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Maximum number of Team Drives to return.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Page token for Team Drives.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"useDomainAdminAccess\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Issue the request as a domain administrator; if set to true, then all Team Drives of the domain in which the requester is an administrator are returned.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/TeamDriveList\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/files/trash\": {\n   \"delete\": {\n    \"operationId\": \"drive.files.emptyTrash\",\n    \"description\": \"Permanently deletes all of the user's trashed files. For more information, see [Trash or delete files and folders](https://developers.google.com/workspace/drive/api/guides/delete).\",\n    \"parameters\": [\n     {\n      \"name\": \"driveId\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"If set, empties the trash of the provided shared drive.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"enforceSingleParent\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: If an item isn't in a shared drive and its last parent is deleted but the item itself isn't, the item will be placed under its owner's root.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\"\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/files\": {\n   \"post\": {\n    \"operationId\": \"drive.files.create\",\n    \"description\": \"Creates a file. For more information, see [Create and manage files](https://developers.google.com/workspace/drive/api/guides/create-file). This method supports an */upload* URI and accepts uploaded media with the following characteristics: - *Maximum file size:* 5,120 GB - *Accepted Media MIME types:* `*/*` (Specify a valid MIME type, rather than the literal `*/*` value. The literal `*/*` is only used to indicate that any valid MIME type can be uploaded. For more information, see [Google Workspace and Google Drive supported MIME types](https://developers.google.com/workspace/drive/api/guides/mime-types).) For more information on uploading files, see [Upload file data](https://developers.google.com/workspace/drive/api/guides/manage-uploads). Apps creating shortcuts with the `create` method must specify the MIME type `application/vnd.google-apps.shortcut`. Apps should specify a file extension in the `name` property when inserting files with the API. For example, an operation to insert a JPEG file should specify something like `\\\"name\\\": \\\"cat.jpg\\\"` in the metadata. Subsequent `GET` requests include the read-only `fileExtension` property populated with the extension originally specified in the `name` property. When a Google Drive user requests to download a file, or when the file is downloaded through the sync client, Drive builds a full filename (with extension) based on the name. In cases where the extension is missing, Drive attempts to determine the extension based on the file's MIME type.\",\n    \"parameters\": [\n     {\n      \"name\": \"includePermissionsForView\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Specifies which additional view's permissions to include in the response. Only `published` is supported.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"ignoreDefaultVisibility\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to ignore the domain's default visibility settings for the created file. Domain administrators can choose to make all uploaded files visible to the domain by default; this parameter bypasses that behavior for the request. Permissions are still inherited from parent folders.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"enforceSingleParent\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: Creating files in multiple folders is no longer supported.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"useContentAsIndexableText\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to use the uploaded content as indexable text.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"ocrLanguage\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"A language hint for OCR processing during image import (ISO 639-1 code).\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"supportsAllDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether the requesting application supports both My Drives and shared drives.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"includeLabels\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"A comma-separated list of IDs of labels to include in the `labelInfo` part of the response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"supportsTeamDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: Use `supportsAllDrives` instead.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"keepRevisionForever\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to set the `keepForever` field in the new head revision. This is only applicable to files with binary content in Google Drive. Only 200 revisions for the file can be kept forever. If the limit is reached, try deleting pinned revisions.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/File\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/File\"\n       }\n      }\n     }\n    }\n   },\n   \"get\": {\n    \"operationId\": \"drive.files.list\",\n    \"description\": \"Lists the user's files. For more information, see [Search for files and folders](https://developers.google.com/workspace/drive/api/guides/search-files). This method accepts the `q` parameter, which is a search query combining one or more search terms. This method returns *all* files by default, including trashed files. If you don't want trashed files to appear in the list, use the `trashed=false` query parameter to remove trashed files from the results.\",\n    \"parameters\": [\n     {\n      \"name\": \"orderBy\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"A comma-separated list of sort keys. Valid keys are: * `createdTime`: When the file was created. Avoid using this key for queries on large item collections as it might result in timeouts or other issues. For time-related sorting on large item collections, use `modifiedTime desc` instead. * `folder`: The folder ID. This field is sorted using alphabetical ordering. * `modifiedByMeTime`: The last time the file was modified by the user. * `modifiedTime`: The last time the file was modified by anyone. * `name`: The name of the file. This field is sorted using alphabetical ordering, so 1, 12, 2, 22. * `name_natural`: The name of the file. This field is sorted using natural sort ordering, so 1, 2, 12, 22. * `quotaBytesUsed`: The number of storage quota bytes used by the file. * `recency`: The most recent timestamp from the file's date-time fields. * `sharedWithMeTime`: When the file was shared with the user, if applicable. * `starred`: Whether the user has starred the file. * `viewedByMeTime`: The last time the file was viewed by the user. Each key sorts ascending by default, but can be reversed with the `desc` modifier. Example usage: `?orderBy=folder,modifiedTime desc,name`.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"includeLabels\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"A comma-separated list of IDs of labels to include in the `labelInfo` part of the response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"teamDriveId\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: Use `driveId` instead.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"supportsAllDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether the requesting application supports both My Drives and shared drives.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"pageSize\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The maximum number of files to return. The service may return fewer than this value. If unspecified, at most 100 files will be returned for shared drives, and the entire list of files for non-shared drives. The maximum value is 1000; values above 1000 will be coerced to 1000.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"includeItemsFromAllDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether both My Drive and shared drive items should be included in results.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"spaces\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"A comma-separated list of spaces to query within the corpora. Supported values are `drive` and `appDataFolder`. For more information, see [File organization](https://developers.google.com/workspace/drive/api/guides/about-files#file-organization).\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"corpus\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: The source of files to list. Use `corpora` instead.\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"enum\": [\n        \"domain\",\n        \"user\"\n       ]\n      }\n     },\n     {\n      \"name\": \"includeTeamDriveItems\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: Use `includeItemsFromAllDrives` instead.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"driveId\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"ID of the shared drive to search.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"supportsTeamDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: Use `supportsAllDrives` instead.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"corpora\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Specifies a collection of items (files or documents) to which the query applies. Supported items include: * `user` * `domain` * `drive` * `allDrives` Prefer `user` or `drive` to `allDrives` for efficiency. By default, corpora is set to `user`. However, this can change depending on the filter set through the `q` parameter. For more information, see [File organization](https://developers.google.com/workspace/drive/api/guides/about-files#file-organization).\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The token for continuing a previous list request on the next page. This should be set to the value of `nextPageToken` from the previous response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"includePermissionsForView\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Specifies which additional view's permissions to include in the response. Only `published` is supported.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"q\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"A query for filtering the file results. For supported syntax, see [Search for files and folders](/workspace/drive/api/guides/search-files).\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/FileList\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/files/generateIds\": {\n   \"get\": {\n    \"operationId\": \"drive.files.generateIds\",\n    \"description\": \"Generates a set of file IDs which can be provided in create or copy requests. For more information, see [Create and manage files](https://developers.google.com/workspace/drive/api/guides/create-file).\",\n    \"parameters\": [\n     {\n      \"name\": \"type\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The type of items which the IDs can be used for. Supported values are `files` and `shortcuts`. Note that `shortcuts` are only supported in the `drive` `space`. (Default: `files`.) For more information, see [File organization](https://developers.google.com/workspace/drive/api/guides/about-files#file-organization).\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"count\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The number of IDs to return.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"space\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The space in which the IDs can be used to create files. Supported values are `drive` and `appDataFolder`. (Default: `drive`.) For more information, see [File organization](https://developers.google.com/workspace/drive/api/guides/about-files#file-organization).\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/GeneratedIds\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/files/{fileId}\": {\n   \"patch\": {\n    \"operationId\": \"drive.files.update\",\n    \"description\": \"Updates a file's metadata, content, or both. When calling this method, only populate fields in the request that you want to modify. When updating fields, some fields might be changed automatically, such as `modifiedDate`. This method supports patch semantics. This method supports an */upload* URI and accepts uploaded media with the following characteristics: - *Maximum file size:* 5,120 GB - *Accepted Media MIME types:* `*/*` (Specify a valid MIME type, rather than the literal `*/*` value. The literal `*/*` is only used to indicate that any valid MIME type can be uploaded. For more information, see [Google Workspace and Google Drive supported MIME types](https://developers.google.com/workspace/drive/api/guides/mime-types).) For more information on uploading files, see [Upload file data](https://developers.google.com/workspace/drive/api/guides/manage-uploads).\",\n    \"parameters\": [\n     {\n      \"name\": \"enforceSingleParent\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: Adding files to multiple folders is no longer supported. Use shortcuts instead.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"supportsTeamDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: Use `supportsAllDrives` instead.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"includeLabels\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"A comma-separated list of IDs of labels to include in the `labelInfo` part of the response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"supportsAllDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether the requesting application supports both My Drives and shared drives.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"ocrLanguage\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"A language hint for OCR processing during image import (ISO 639-1 code).\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"includePermissionsForView\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Specifies which additional view's permissions to include in the response. Only `published` is supported.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"removeParents\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"A comma-separated list of parent IDs to remove.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"addParents\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"A comma-separated list of parent IDs to add.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"keepRevisionForever\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to set the `keepForever` field in the new head revision. This is only applicable to files with binary content in Google Drive. Only 200 revisions for the file can be kept forever. If the limit is reached, try deleting pinned revisions.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"useContentAsIndexableText\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to use the uploaded content as indexable text.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/File\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/File\"\n       }\n      }\n     }\n    }\n   },\n   \"get\": {\n    \"operationId\": \"drive.files.get\",\n    \"description\": \"Gets a file's metadata or content by ID. For more information, see [Search for files and folders](https://developers.google.com/workspace/drive/api/guides/search-files). If you provide the URL parameter `alt=media`, then the response includes the file contents in the response body. Downloading content with `alt=media` only works if the file is stored in Drive. To download Google Docs, Sheets, and Slides use [`files.export`](https://developers.google.com/workspace/drive/api/reference/rest/v3/files/export) instead. For more information, see [Download and export files](https://developers.google.com/workspace/drive/api/guides/manage-downloads).\",\n    \"parameters\": [\n     {\n      \"name\": \"acknowledgeAbuse\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether the user is acknowledging the risk of downloading known malware or other abusive files. This is only applicable when the `alt` parameter is set to `media` and the user is the owner of the file or an organizer of the shared drive in which the file resides.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"includeLabels\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"A comma-separated list of IDs of labels to include in the `labelInfo` part of the response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"supportsAllDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether the requesting application supports both My Drives and shared drives.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"supportsTeamDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: Use `supportsAllDrives` instead.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"includePermissionsForView\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Specifies which additional view's permissions to include in the response. Only `published` is supported.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/File\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   },\n   \"delete\": {\n    \"operationId\": \"drive.files.delete\",\n    \"description\": \"Permanently deletes a file owned by the user without moving it to the trash. For more information, see [Trash or delete files and folders](https://developers.google.com/workspace/drive/api/guides/delete). If the file belongs to a shared drive, the user must be an `organizer` on the parent folder. If the target is a folder, all descendants owned by the user are also deleted.\",\n    \"parameters\": [\n     {\n      \"name\": \"enforceSingleParent\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: If an item isn't in a shared drive and its last parent is deleted but the item itself isn't, the item will be placed under its owner's root.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"supportsAllDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether the requesting application supports both My Drives and shared drives.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"supportsTeamDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: Use `supportsAllDrives` instead.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\"\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/files/{fileId}/listLabels\": {\n   \"get\": {\n    \"operationId\": \"drive.files.listLabels\",\n    \"description\": \"Lists the labels on a file. For more information, see [List labels on a file](https://developers.google.com/workspace/drive/api/guides/list-labels).\",\n    \"parameters\": [\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The token for continuing a previous list request on the next page. This should be set to the value of `nextPageToken` from the previous response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID for the file.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"maxResults\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The maximum number of labels to return per page. When not set, defaults to 100.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/LabelList\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/files/{fileId}/export\": {\n   \"get\": {\n    \"operationId\": \"drive.files.export\",\n    \"description\": \"Exports a Google Workspace document to the requested MIME type and returns exported byte content. For more information, see [Download and export files](https://developers.google.com/workspace/drive/api/guides/manage-downloads). Note that the exported content is limited to 10 MB.\",\n    \"parameters\": [\n     {\n      \"name\": \"mimeType\",\n      \"in\": \"query\",\n      \"required\": true,\n      \"description\": \"Required. The MIME type of the format requested for this export. For a list of supported MIME types, see [Export MIME types for Google Workspace documents](/workspace/drive/api/guides/ref-export-formats).\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\"\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/files/{fileId}/watch\": {\n   \"post\": {\n    \"operationId\": \"drive.files.watch\",\n    \"description\": \"Subscribes to changes to a file. For more information, see [Notifications for resource changes](https://developers.google.com/workspace/drive/api/guides/push).\",\n    \"parameters\": [\n     {\n      \"name\": \"includePermissionsForView\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Specifies which additional view's permissions to include in the response. Only `published` is supported.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"supportsTeamDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: Use `supportsAllDrives` instead.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"supportsAllDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether the requesting application supports both My Drives and shared drives.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"acknowledgeAbuse\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether the user is acknowledging the risk of downloading known malware or other abusive files. This is only applicable when the `alt` parameter is set to `media` and the user is the owner of the file or an organizer of the shared drive in which the file resides.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"includeLabels\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"A comma-separated list of IDs of labels to include in the `labelInfo` part of the response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Channel\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Channel\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/files/{fileId}/modifyLabels\": {\n   \"post\": {\n    \"operationId\": \"drive.files.modifyLabels\",\n    \"description\": \"Modifies the set of labels applied to a file. For more information, see [Set a label field on a file](https://developers.google.com/workspace/drive/api/guides/set-label). Returns a list of the labels that were added or modified.\",\n    \"parameters\": [\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file to which the labels belong.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/ModifyLabelsResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/ModifyLabelsRequest\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/files/{fileId}/copy\": {\n   \"post\": {\n    \"operationId\": \"drive.files.copy\",\n    \"description\": \"Creates a copy of a file and applies any requested updates with patch semantics. For more information, see [Create and manage files](https://developers.google.com/workspace/drive/api/guides/create-file).\",\n    \"parameters\": [\n     {\n      \"name\": \"ocrLanguage\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"A language hint for OCR processing during image import (ISO 639-1 code).\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"includePermissionsForView\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Specifies which additional view's permissions to include in the response. Only `published` is supported.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"supportsTeamDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: Use `supportsAllDrives` instead.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"copyComments\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to copy the open (unresolved) comments associated with the file.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"keepRevisionForever\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to set the `keepForever` field in the new head revision. This is only applicable to files with binary content in Google Drive. Only 200 revisions for the file can be kept forever. If the limit is reached, try deleting pinned revisions.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"supportsAllDrives\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether the requesting application supports both My Drives and shared drives.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"includeLabels\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"A comma-separated list of IDs of labels to include in the `labelInfo` part of the response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"ignoreDefaultVisibility\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to ignore the domain's default visibility settings for the created file. Domain administrators can choose to make all uploaded files visible to the domain by default; this parameter bypasses that behavior for the request. Permissions are still inherited from parent folders.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"enforceSingleParent\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Deprecated: Copying files into multiple folders is no longer supported. Use shortcuts instead.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/File\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/File\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/files/{fileId}/download\": {\n   \"post\": {\n    \"operationId\": \"drive.files.download\",\n    \"description\": \"Downloads the content of a file. For more information, see [Download and export files](https://developers.google.com/workspace/drive/api/guides/manage-downloads). Operations are valid for 24 hours from the time of creation.\",\n    \"parameters\": [\n     {\n      \"name\": \"revisionId\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. The revision ID of the file to download. This field can only be set when downloading blob files, Google Docs, and Google Sheets. Returns `INVALID_ARGUMENT` if downloading a specific revision on the file is unsupported.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"mimeType\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. The MIME type the file should be downloaded as. This field can only be set when downloading Google Workspace documents. For a list of supported MIME types, see [Export MIME types for Google Workspace documents](/workspace/drive/api/guides/ref-export-formats). If not set, a Google Workspace document is downloaded with a default MIME type. The default MIME type might change in the future.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Required. The ID of the file to download.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Operation\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/files/generateCseToken\": {\n   \"get\": {\n    \"operationId\": \"drive.files.generateCseToken\",\n    \"description\": \"Generates a CSE token which can be used to create or update CSE files.\",\n    \"parameters\": [\n     {\n      \"name\": \"fileId\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The ID of the file for which the JWT should be generated. If not provided, an id will be generated.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"parent\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The ID of the expected parent of the file. Used when generating a JWT for a new CSE file. If specified, the parent will be fetched, and if the parent is a shared drive item, the shared drive's policy will be used to determine the KACLS that should be used. It is invalid to specify both file_id and parent in a single request.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/GenerateCseTokenResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/files/{fileId}/comments/{commentId}/replies/{replyId}\": {\n   \"patch\": {\n    \"operationId\": \"drive.replies.update\",\n    \"description\": \"Updates a reply with patch semantics. For more information, see [Manage comments and replies](https://developers.google.com/workspace/drive/api/guides/manage-comments).\",\n    \"parameters\": [\n     {\n      \"name\": \"replyId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the reply.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"commentId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the comment.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Reply\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Reply\"\n       }\n      }\n     }\n    }\n   },\n   \"get\": {\n    \"operationId\": \"drive.replies.get\",\n    \"description\": \"Gets a reply by ID. For more information, see [Manage comments and replies](https://developers.google.com/workspace/drive/api/guides/manage-comments).\",\n    \"parameters\": [\n     {\n      \"name\": \"replyId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the reply.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"commentId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the comment.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"includeDeleted\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to return deleted replies. Deleted replies don't include their original content.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Reply\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   },\n   \"delete\": {\n    \"operationId\": \"drive.replies.delete\",\n    \"description\": \"Deletes a reply. For more information, see [Manage comments and replies](https://developers.google.com/workspace/drive/api/guides/manage-comments).\",\n    \"parameters\": [\n     {\n      \"name\": \"commentId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the comment.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"replyId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the reply.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\"\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/files/{fileId}/comments/{commentId}/replies\": {\n   \"post\": {\n    \"operationId\": \"drive.replies.create\",\n    \"description\": \"Creates a reply to a comment. For more information, see [Manage comments and replies](https://developers.google.com/workspace/drive/api/guides/manage-comments).\",\n    \"parameters\": [\n     {\n      \"name\": \"commentId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the comment.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Reply\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Reply\"\n       }\n      }\n     }\n    }\n   },\n   \"get\": {\n    \"operationId\": \"drive.replies.list\",\n    \"description\": \"Lists a comment's replies. For more information, see [Manage comments and replies](https://developers.google.com/workspace/drive/api/guides/manage-comments).\",\n    \"parameters\": [\n     {\n      \"name\": \"commentId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the comment.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"includeDeleted\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to include deleted replies. Deleted replies don't include their original content.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The token for continuing a previous list request on the next page. This should be set to the value of `nextPageToken` from the previous response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"pageSize\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The maximum number of replies to return. The service may return fewer than this value. If unspecified, at most 20 replies will be returned. The maximum value is 100; values above 100 will be coerced to 100.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/ReplyList\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/files/{fileId}/revisions\": {\n   \"get\": {\n    \"operationId\": \"drive.revisions.list\",\n    \"description\": \"Lists a file's revisions. For more information, see [Manage file revisions](https://developers.google.com/workspace/drive/api/guides/manage-revisions). **Important:** The list of revisions returned by this method might be incomplete for files with a large revision history, including frequently edited Google Docs, Sheets, and Slides. Older revisions might be omitted from the response, meaning the first revision returned may not be the oldest existing revision. The revision history visible in the Workspace editor user interface might be more complete than the list returned by the API.\",\n    \"parameters\": [\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"pageSize\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The maximum number of revisions to return. The service may return fewer than this value. If unspecified, at most 200 revisions will be returned. The maximum value is 1000; values above 1000 will be coerced to 1000.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/RevisionList\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/files/{fileId}/revisions/{revisionId}\": {\n   \"delete\": {\n    \"operationId\": \"drive.revisions.delete\",\n    \"description\": \"Permanently deletes a file version. You can only delete revisions for files with binary content in Google Drive, like images or videos. Revisions for other files, like Google Docs or Sheets, and the last remaining file version can't be deleted. For more information, see [Manage file revisions](https://developers.google.com/drive/api/guides/manage-revisions).\",\n    \"parameters\": [\n     {\n      \"name\": \"revisionId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the revision.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\"\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   },\n   \"patch\": {\n    \"operationId\": \"drive.revisions.update\",\n    \"description\": \"Updates a revision with patch semantics. For more information, see [Manage file revisions](https://developers.google.com/workspace/drive/api/guides/manage-revisions).\",\n    \"parameters\": [\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"revisionId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the revision.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Revision\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Revision\"\n       }\n      }\n     }\n    }\n   },\n   \"get\": {\n    \"operationId\": \"drive.revisions.get\",\n    \"description\": \"Gets a revision's metadata or content by ID. For more information, see [Manage file revisions](https://developers.google.com/workspace/drive/api/guides/manage-revisions).\",\n    \"parameters\": [\n     {\n      \"name\": \"revisionId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the revision.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"acknowledgeAbuse\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether the user is acknowledging the risk of downloading known malware or other abusive files. This is only applicable when the `alt` parameter is set to `media` and the user is the owner of the file or an organizer of the shared drive in which the file resides.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Revision\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/files/{fileId}/approvals/{approvalId}:reassign\": {\n   \"post\": {\n    \"operationId\": \"drive.approvals.reassign\",\n    \"description\": \"Reassigns the reviewers on an approval. For more information, see [Manage approvals](https://developers.google.com/workspace/drive/api/guides/approvals). Adds or replaces reviewers in the ReviewerResponse of the approval. This can be called by any user with the `writer` permission on the file while the approval Status is `IN_PROGRESS` and the Response for the reviewer being reassigned is `NO_RESPONSE`. A user with the `reader` permission can only reassign an approval that's assigned to themselves. Removing a reviewer isn't allowed.\",\n    \"parameters\": [\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Required. The ID of the file that the approval is on.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"approvalId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Required. The ID of the approval to reassign.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Approval\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/ReassignApprovalRequest\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/files/{fileId}/approvals\": {\n   \"get\": {\n    \"operationId\": \"drive.approvals.list\",\n    \"description\": \"Lists the approvals on a file. For more information, see [Manage approvals](https://developers.google.com/workspace/drive/api/guides/approvals). By default, this method returns a minimal response that may not include the items array. To retrieve approval details, you must explicitly specify the fields you want using the `fields` query parameter. To return the exact fields you need, see [Return specific fields](https://developers.google.com/workspace/drive/api/guides/fields-parameter).\",\n    \"parameters\": [\n     {\n      \"name\": \"pageSize\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The maximum number of approvals to return. When not set, at most 100 approvals are returned.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Required. The ID of the file that the approval is on.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The token for continuing a previous list request on the next page. This should be set to the value of `nextPageToken` from a previous response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/ApprovalList\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/files/{fileId}/approvals/{approvalId}:decline\": {\n   \"post\": {\n    \"operationId\": \"drive.approvals.decline\",\n    \"description\": \"Declines an approval. For more information, see [Manage approvals](https://developers.google.com/workspace/drive/api/guides/approvals). This is used to update the ReviewerResponse of the requesting user with a Response of `DECLINED`. This also completes the approval and sets the approval Status to `DECLINED`.\",\n    \"parameters\": [\n     {\n      \"name\": \"approvalId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Required. The ID of the approval to decline.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Required. The ID of the file that the approval is on.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Approval\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/DeclineApprovalRequest\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/files/{fileId}/approvals/{approvalId}:cancel\": {\n   \"post\": {\n    \"operationId\": \"drive.approvals.cancel\",\n    \"description\": \"Cancels an approval. For more information, see [Manage approvals](https://developers.google.com/workspace/drive/api/guides/approvals). Updates the approval Status to `CANCELLED`. This can be called by any user with the `writer` permission on the file while the approval Status is `IN_PROGRESS`.\",\n    \"parameters\": [\n     {\n      \"name\": \"approvalId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Required. The ID of the approval to cancel.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Required. The ID of the file that the approval is on.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Approval\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/CancelApprovalRequest\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/files/{fileId}/approvals:start\": {\n   \"post\": {\n    \"operationId\": \"drive.approvals.start\",\n    \"description\": \"Starts an approval on a file. For more information, see [Manage approvals](https://developers.google.com/workspace/drive/api/guides/approvals).\",\n    \"parameters\": [\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Required. The ID of the file that the approval is created on.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Approval\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/StartApprovalRequest\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/files/{fileId}/approvals/{approvalId}\": {\n   \"get\": {\n    \"operationId\": \"drive.approvals.get\",\n    \"description\": \"Gets an approval by ID. For more information, see [Manage approvals](https://developers.google.com/workspace/drive/api/guides/approvals).\",\n    \"parameters\": [\n     {\n      \"name\": \"approvalId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Required. The ID of the approval.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Required. The ID of the file that the approval is on.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Approval\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/files/{fileId}/approvals/{approvalId}:approve\": {\n   \"post\": {\n    \"operationId\": \"drive.approvals.approve\",\n    \"description\": \"Approves an approval. For more information, see [Manage approvals](https://developers.google.com/workspace/drive/api/guides/approvals). This is used to update the ReviewerResponse of the requesting user with a Response of `APPROVED`. If this is the last required reviewer response, this also completes the approval and sets the approval Status to `APPROVED`.\",\n    \"parameters\": [\n     {\n      \"name\": \"approvalId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Required. The ID of the approval to approve.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Required. The ID of the file that the approval is on.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Approval\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/ApproveApprovalRequest\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/files/{fileId}/approvals/{approvalId}:comment\": {\n   \"post\": {\n    \"operationId\": \"drive.approvals.comment\",\n    \"description\": \"Comments on an approval. For more information, see [Manage approvals](https://developers.google.com/workspace/drive/api/guides/approvals). This sends a notification to both the initiator and the reviewers. Additionally, a message is also added to the approval activity log.\",\n    \"parameters\": [\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Required. The ID of the file that the approval is on.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"approvalId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Required. The ID of the approval to comment on.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Approval\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/CommentApprovalRequest\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/files/{fileId}/comments\": {\n   \"get\": {\n    \"operationId\": \"drive.comments.list\",\n    \"description\": \"Lists a file's comments. For more information, see [Manage comments and replies](https://developers.google.com/workspace/drive/api/guides/manage-comments). Required: The `fields` parameter must be set. To return the exact fields you need, see [Return specific fields](https://developers.google.com/workspace/drive/api/guides/fields-parameter).\",\n    \"parameters\": [\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"startModifiedTime\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The minimum value of 'modifiedTime' for the result comments (RFC 3339 date-time).\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"pageSize\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"The maximum number of comments to return. The service may return fewer than this value. If unspecified, at most 20 comments will be returned. The maximum value is 100; values above 100 will be coerced to 100.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"includeDeleted\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to include deleted comments. Deleted comments will not include their original content.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/CommentList\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   },\n   \"post\": {\n    \"operationId\": \"drive.comments.create\",\n    \"description\": \"Creates a comment on a file. For more information, see [Manage comments and replies](https://developers.google.com/workspace/drive/api/guides/manage-comments). Required: The `fields` parameter must be set. To return the exact fields you need, see [Return specific fields](https://developers.google.com/workspace/drive/api/guides/fields-parameter).\",\n    \"parameters\": [\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Comment\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Comment\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/files/{fileId}/comments/{commentId}\": {\n   \"patch\": {\n    \"operationId\": \"drive.comments.update\",\n    \"description\": \"Updates a comment with patch semantics. For more information, see [Manage comments and replies](https://developers.google.com/workspace/drive/api/guides/manage-comments). Required: The `fields` parameter must be set. To return the exact fields you need, see [Return specific fields](https://developers.google.com/workspace/drive/api/guides/fields-parameter).\",\n    \"parameters\": [\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"commentId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the comment.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Comment\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Comment\"\n       }\n      }\n     }\n    }\n   },\n   \"get\": {\n    \"operationId\": \"drive.comments.get\",\n    \"description\": \"Gets a comment by ID. For more information, see [Manage comments and replies](https://developers.google.com/workspace/drive/api/guides/manage-comments). Required: The `fields` parameter must be set. To return the exact fields you need, see [Return specific fields](https://developers.google.com/workspace/drive/api/guides/fields-parameter).\",\n    \"parameters\": [\n     {\n      \"name\": \"includeDeleted\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Whether to return deleted comments. Deleted comments will not include their original content.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"commentId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the comment.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Comment\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   },\n   \"delete\": {\n    \"operationId\": \"drive.comments.delete\",\n    \"description\": \"Deletes a comment. For more information, see [Manage comments and replies](https://developers.google.com/workspace/drive/api/guides/manage-comments).\",\n    \"parameters\": [\n     {\n      \"name\": \"commentId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the comment.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"The ID of the file.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\"\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/files/{fileId}/accessproposals\": {\n   \"get\": {\n    \"operationId\": \"drive.accessproposals.list\",\n    \"description\": \"List the access proposals on a file. For more information, see [Manage pending access proposals](https://developers.google.com/workspace/drive/api/guides/pending-access). Note: Only approvers are able to list access proposals on a file. If the user isn't an approver, a 403 error is returned.\",\n    \"parameters\": [\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Required. The ID of the item the request is on.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"pageSize\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. The number of results per page.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. The continuation token on the list of access requests.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/ListAccessProposalsResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/files/{fileId}/accessproposals/{proposalId}\": {\n   \"get\": {\n    \"operationId\": \"drive.accessproposals.get\",\n    \"description\": \"Retrieves an access proposal by ID. For more information, see [Manage pending access proposals](https://developers.google.com/workspace/drive/api/guides/pending-access).\",\n    \"parameters\": [\n     {\n      \"name\": \"proposalId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Required. The ID of the access proposal to resolve.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Required. The ID of the item the request is on.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/AccessProposal\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/files/{fileId}/accessproposals/{proposalId}:resolve\": {\n   \"post\": {\n    \"operationId\": \"drive.accessproposals.resolve\",\n    \"description\": \"Approves or denies an access proposal. For more information, see [Manage pending access proposals](https://developers.google.com/workspace/drive/api/guides/pending-access).\",\n    \"parameters\": [\n     {\n      \"name\": \"proposalId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Required. The ID of the access proposal to resolve.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fileId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Required. The ID of the item the request is on.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\"\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/ResolveAccessProposalRequest\"\n       }\n      }\n     }\n    }\n   }\n  }\n },\n \"components\": {\n  \"schemas\": {\n   \"Revision\": {\n    \"description\": \"The metadata for a revision to a file. Some resource methods (such as `revisions.update`) require a `revisionId`. Use the `revisions.list` method to retrieve the ID for a revision.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"id\": {\n      \"description\": \"Output only. The ID of the revision.\",\n      \"type\": \"string\"\n     },\n     \"mimeType\": {\n      \"description\": \"Output only. The MIME type of the revision.\",\n      \"type\": \"string\"\n     },\n     \"modifiedTime\": {\n      \"description\": \"The last time the revision was modified (RFC 3339 date-time).\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     },\n     \"size\": {\n      \"description\": \"Output only. The size of the revision's content in bytes. This is only applicable to files with binary content in Drive.\",\n      \"type\": \"string\",\n      \"format\": \"int64\"\n     },\n     \"keepForever\": {\n      \"description\": \"Whether to keep this revision forever, even if it is no longer the head revision. If not set, the revision will be automatically purged 30 days after newer content is uploaded. This can be set on a maximum of 200 revisions for a file. This field is only applicable to files with binary content in Drive.\",\n      \"type\": \"boolean\"\n     },\n     \"kind\": {\n      \"description\": \"Output only. Identifies what kind of resource this is. Value: the fixed string `\\\"drive#revision\\\"`.\",\n      \"type\": \"string\"\n     },\n     \"publishAuto\": {\n      \"description\": \"Whether subsequent revisions will be automatically republished. This is only applicable to Docs Editors files.\",\n      \"type\": \"boolean\"\n     },\n     \"originalFilename\": {\n      \"description\": \"Output only. The original filename used to create this revision. This is only applicable to files with binary content in Drive.\",\n      \"type\": \"string\"\n     },\n     \"exportLinks\": {\n      \"description\": \"Output only. Links for exporting Docs Editors files to specific formats.\",\n      \"type\": \"object\",\n      \"additionalProperties\": {\n       \"type\": \"string\"\n      }\n     },\n     \"publishedOutsideDomain\": {\n      \"description\": \"Whether this revision is published outside the domain. This is only applicable to Docs Editors files.\",\n      \"type\": \"boolean\"\n     },\n     \"md5Checksum\": {\n      \"description\": \"Output only. The MD5 checksum of the revision's content. This is only applicable to files with binary content in Drive.\",\n      \"type\": \"string\"\n     },\n     \"publishedLink\": {\n      \"description\": \"Output only. A link to the published revision. This is only populated for Docs Editors files.\",\n      \"type\": \"string\"\n     },\n     \"published\": {\n      \"description\": \"Whether this revision is published. This is only applicable to Docs Editors files.\",\n      \"type\": \"boolean\"\n     },\n     \"lastModifyingUser\": {\n      \"$ref\": \"#/components/schemas/User\"\n     }\n    }\n   },\n   \"LabelFieldModification\": {\n    \"description\": \"A modification to a label's field.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"setSelectionValues\": {\n      \"description\": \"Replaces a `selection` field with these new values.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"setUserValues\": {\n      \"description\": \"Replaces a `user` field with these new values. The values must be a valid email addresses.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"setIntegerValues\": {\n      \"description\": \"Replaces the value of an `integer` field with these new values.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\",\n       \"format\": \"int64\"\n      }\n     },\n     \"setTextValues\": {\n      \"description\": \"Sets the value of a `text` field.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"fieldId\": {\n      \"description\": \"The ID of the field to be modified.\",\n      \"type\": \"string\"\n     },\n     \"kind\": {\n      \"description\": \"This is always `\\\"drive#labelFieldModification\\\"`.\",\n      \"type\": \"string\"\n     },\n     \"setDateValues\": {\n      \"description\": \"Replaces the value of a dateString Field with these new values. The string must be in the RFC 3339 full-date format: YYYY-MM-DD.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\",\n       \"format\": \"date\"\n      }\n     },\n     \"unsetValues\": {\n      \"description\": \"Unsets the values for this field.\",\n      \"type\": \"boolean\"\n     }\n    }\n   },\n   \"Label\": {\n    \"description\": \"Representation of label and label fields.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"id\": {\n      \"description\": \"The ID of the label.\",\n      \"type\": \"string\"\n     },\n     \"kind\": {\n      \"description\": \"This is always drive#label\",\n      \"type\": \"string\"\n     },\n     \"fields\": {\n      \"description\": \"A map of the fields on the label, keyed by the field's ID.\",\n      \"type\": \"object\",\n      \"additionalProperties\": {\n       \"$ref\": \"#/components/schemas/LabelField\"\n      }\n     },\n     \"revisionId\": {\n      \"description\": \"The revision ID of the label.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"ChangeList\": {\n    \"description\": \"A list of changes for a user.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"changes\": {\n      \"description\": \"The list of changes. If nextPageToken is populated, then this list may be incomplete and an additional page of results should be fetched.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Change\"\n      }\n     },\n     \"newStartPageToken\": {\n      \"description\": \"The starting page token for future changes. This will be present only if the end of the current changes list has been reached. The page token doesn't expire.\",\n      \"type\": \"string\"\n     },\n     \"kind\": {\n      \"description\": \"Identifies what kind of resource this is. Value: the fixed string `\\\"drive#changeList\\\"`.\",\n      \"type\": \"string\"\n     },\n     \"nextPageToken\": {\n      \"description\": \"The page token for the next page of changes. This will be absent if the end of the changes list has been reached. The page token doesn't expire.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"ReplyList\": {\n    \"description\": \"A list of replies to a comment on a file.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"kind\": {\n      \"description\": \"Identifies what kind of resource this is. Value: the fixed string `\\\"drive#replyList\\\"`.\",\n      \"type\": \"string\"\n     },\n     \"replies\": {\n      \"description\": \"The list of replies. If `nextPageToken` is populated, then this list may be incomplete and an additional page of results should be fetched.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Reply\"\n      }\n     },\n     \"nextPageToken\": {\n      \"description\": \"The page token for the next page of replies. This will be absent if the end of the replies list has been reached. If the token is rejected for any reason, it should be discarded, and pagination should be restarted from the first page of results. The page token is typically valid for several hours. However, if new items are added or removed, your expected results might differ.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"ClientEncryptionDetails\": {\n    \"description\": \"Details about the client-side encryption applied to the file.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"encryptionState\": {\n      \"description\": \"The encryption state of the file. The values expected here are: - encrypted - unencrypted \",\n      \"type\": \"string\"\n     },\n     \"decryptionMetadata\": {\n      \"$ref\": \"#/components/schemas/DecryptionMetadata\"\n     }\n    }\n   },\n   \"GenerateCseTokenResponse\": {\n    \"description\": \"JWT and associated metadata used to generate CSE files.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"fileId\": {\n      \"description\": \"The fileId for which the JWT was generated.\",\n      \"type\": \"string\"\n     },\n     \"jwt\": {\n      \"description\": \"The signed JSON Web Token (JWT) for the file.\",\n      \"type\": \"string\"\n     },\n     \"kind\": {\n      \"description\": \"Output only. Identifies what kind of resource this is. Value: the fixed string `\\\"drive#generateCseTokenResponse\\\"`.\",\n      \"type\": \"string\"\n     },\n     \"currentKaclsId\": {\n      \"description\": \"The current Key ACL Service (KACLS) ID associated with the JWT.\",\n      \"type\": \"string\",\n      \"format\": \"int64\"\n     },\n     \"currentKaclsName\": {\n      \"description\": \"Name of the KACLs that the returned KACLs ID points to.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"ReplaceReviewer\": {\n    \"description\": \"Representation of a reviewer replacement.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"removedReviewerEmail\": {\n      \"description\": \"Required. The email of the reviewer to remove.\",\n      \"type\": \"string\"\n     },\n     \"addedReviewerEmail\": {\n      \"description\": \"Required. The email of the reviewer to add.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"About\": {\n    \"description\": \"Information about the user, the user's Drive, and system capabilities.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"user\": {\n      \"$ref\": \"#/components/schemas/User\"\n     },\n     \"canCreateDrives\": {\n      \"description\": \"Whether the user can create shared drives.\",\n      \"type\": \"boolean\"\n     },\n     \"appInstalled\": {\n      \"description\": \"Whether the user has installed the requesting app.\",\n      \"type\": \"boolean\"\n     },\n     \"storageQuota\": {\n      \"description\": \"The user's storage quota limits and usage. For users that are part of an organization with pooled storage, information about the limit and usage across all services is for the organization, rather than the individual user. All fields are measured in bytes.\",\n      \"type\": \"object\",\n      \"properties\": {\n       \"usageInDrive\": {\n        \"description\": \"The usage by all files in Google Drive.\",\n        \"type\": \"string\",\n        \"format\": \"int64\"\n       },\n       \"limit\": {\n        \"description\": \"The usage limit, if applicable. This will not be present if the user has unlimited storage. For users that are part of an organization with pooled storage, this is the limit for the organization, rather than the individual user.\",\n        \"type\": \"string\",\n        \"format\": \"int64\"\n       },\n       \"usageInDriveTrash\": {\n        \"description\": \"The usage by trashed files in Google Drive.\",\n        \"type\": \"string\",\n        \"format\": \"int64\"\n       },\n       \"usage\": {\n        \"description\": \"The total usage across all services. For users that are part of an organization with pooled storage, this is the usage across all services for the organization, rather than the individual user.\",\n        \"type\": \"string\",\n        \"format\": \"int64\"\n       }\n      }\n     },\n     \"driveThemes\": {\n      \"description\": \"A list of themes that are supported for shared drives.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"object\",\n       \"properties\": {\n        \"id\": {\n         \"description\": \"The ID of the theme.\",\n         \"type\": \"string\"\n        },\n        \"backgroundImageLink\": {\n         \"description\": \"A link to this theme's background image.\",\n         \"type\": \"string\"\n        },\n        \"colorRgb\": {\n         \"description\": \"The color of this theme as an RGB hex string.\",\n         \"type\": \"string\"\n        }\n       }\n      }\n     },\n     \"importFormats\": {\n      \"description\": \"A map of source MIME type to possible targets for all supported imports.\",\n      \"type\": \"object\",\n      \"additionalProperties\": {\n       \"type\": \"array\",\n       \"items\": {\n        \"type\": \"string\"\n       }\n      }\n     },\n     \"exportFormats\": {\n      \"description\": \"A map of source MIME type to possible targets for all supported exports.\",\n      \"type\": \"object\",\n      \"additionalProperties\": {\n       \"type\": \"array\",\n       \"items\": {\n        \"type\": \"string\"\n       }\n      }\n     },\n     \"kind\": {\n      \"description\": \"Identifies what kind of resource this is. Value: the fixed string `\\\"drive#about\\\"`.\",\n      \"type\": \"string\"\n     },\n     \"maxImportSizes\": {\n      \"description\": \"A map of maximum import sizes by MIME type, in bytes.\",\n      \"type\": \"object\",\n      \"additionalProperties\": {\n       \"type\": \"string\",\n       \"format\": \"int64\"\n      }\n     },\n     \"canCreateTeamDrives\": {\n      \"description\": \"Deprecated: Use `canCreateDrives` instead.\",\n      \"type\": \"boolean\"\n     },\n     \"teamDriveThemes\": {\n      \"description\": \"Deprecated: Use `driveThemes` instead.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"object\",\n       \"properties\": {\n        \"id\": {\n         \"description\": \"Deprecated: Use `driveThemes/id` instead.\",\n         \"type\": \"string\"\n        },\n        \"colorRgb\": {\n         \"description\": \"Deprecated: Use `driveThemes/colorRgb` instead.\",\n         \"type\": \"string\"\n        },\n        \"backgroundImageLink\": {\n         \"description\": \"Deprecated: Use `driveThemes/backgroundImageLink` instead.\",\n         \"type\": \"string\"\n        }\n       }\n      }\n     },\n     \"folderColorPalette\": {\n      \"description\": \"The currently supported folder colors as RGB hex strings.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"maxUploadSize\": {\n      \"description\": \"The maximum upload size in bytes.\",\n      \"type\": \"string\",\n      \"format\": \"int64\"\n     }\n    }\n   },\n   \"Channel\": {\n    \"description\": \"A notification channel used to watch for resource changes.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"token\": {\n      \"description\": \"An arbitrary string delivered to the target address with each notification delivered over this channel. Optional.\",\n      \"type\": \"string\"\n     },\n     \"params\": {\n      \"description\": \"Additional parameters controlling delivery channel behavior. Optional.\",\n      \"type\": \"object\",\n      \"additionalProperties\": {\n       \"type\": \"string\"\n      }\n     },\n     \"kind\": {\n      \"description\": \"Identifies this as a notification channel used to watch for changes to a resource, which is `api#channel`.\",\n      \"type\": \"string\"\n     },\n     \"expiration\": {\n      \"description\": \"Date and time of notification channel expiration, expressed as a Unix timestamp, in milliseconds. Optional.\",\n      \"type\": \"string\",\n      \"format\": \"int64\"\n     },\n     \"id\": {\n      \"description\": \"A UUID or similar unique string that identifies this channel.\",\n      \"type\": \"string\"\n     },\n     \"resourceId\": {\n      \"description\": \"An opaque ID that identifies the resource being watched on this channel. Stable across different API versions.\",\n      \"type\": \"string\"\n     },\n     \"payload\": {\n      \"description\": \"A Boolean value to indicate whether payload is wanted. Optional.\",\n      \"type\": \"boolean\"\n     },\n     \"type\": {\n      \"description\": \"The type of delivery mechanism used for this channel. Valid values are \\\"web_hook\\\" or \\\"webhook\\\".\",\n      \"type\": \"string\"\n     },\n     \"resourceUri\": {\n      \"description\": \"A version-specific identifier for the watched resource.\",\n      \"type\": \"string\"\n     },\n     \"address\": {\n      \"description\": \"The address where notifications are delivered for this channel.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"Change\": {\n    \"description\": \"A change to a file or shared drive.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"time\": {\n      \"description\": \"The time of this change (RFC 3339 date-time).\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     },\n     \"changeType\": {\n      \"description\": \"The type of the change. Possible values are `file` and `drive`.\",\n      \"type\": \"string\"\n     },\n     \"type\": {\n      \"description\": \"Deprecated: Use `changeType` instead.\",\n      \"type\": \"string\"\n     },\n     \"teamDrive\": {\n      \"$ref\": \"#/components/schemas/TeamDrive\"\n     },\n     \"teamDriveId\": {\n      \"description\": \"Deprecated: Use `driveId` instead.\",\n      \"type\": \"string\"\n     },\n     \"fileId\": {\n      \"description\": \"The ID of the file which has changed.\",\n      \"type\": \"string\"\n     },\n     \"removed\": {\n      \"description\": \"Whether the file or shared drive has been removed from this list of changes, for example by deletion or loss of access.\",\n      \"type\": \"boolean\"\n     },\n     \"file\": {\n      \"$ref\": \"#/components/schemas/File\"\n     },\n     \"drive\": {\n      \"$ref\": \"#/components/schemas/Drive\"\n     },\n     \"driveId\": {\n      \"description\": \"The ID of the shared drive associated with this change.\",\n      \"type\": \"string\"\n     },\n     \"kind\": {\n      \"description\": \"Identifies what kind of resource this is. Value: the fixed string `\\\"drive#change\\\"`.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"PermissionList\": {\n    \"description\": \"A list of permissions for a file.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"kind\": {\n      \"description\": \"Identifies what kind of resource this is. Value: the fixed string `\\\"drive#permissionList\\\"`.\",\n      \"type\": \"string\"\n     },\n     \"nextPageToken\": {\n      \"description\": \"The page token for the next page of permissions. This field will be absent if the end of the permissions list has been reached. If the token is rejected for any reason, it should be discarded, and pagination should be restarted from the first page of results. The page token is typically valid for several hours. However, if new items are added or removed, your expected results might differ.\",\n      \"type\": \"string\"\n     },\n     \"permissions\": {\n      \"description\": \"The list of permissions. If `nextPageToken` is populated, then this list may be incomplete and an additional page of results should be fetched.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Permission\"\n      }\n     }\n    }\n   },\n   \"ResolveAccessProposalRequest\": {\n    \"description\": \"Request message for resolving an AccessProposal on a file.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"sendNotification\": {\n      \"description\": \"Optional. Whether to send an email to the requester when the access proposal is denied or accepted.\",\n      \"type\": \"boolean\"\n     },\n     \"action\": {\n      \"description\": \"Required. The action to take on the access proposal.\",\n      \"type\": \"string\",\n      \"enum\": [\n       \"ACTION_UNSPECIFIED\",\n       \"ACCEPT\",\n       \"DENY\"\n      ]\n     },\n     \"role\": {\n      \"description\": \"Optional. The roles that the approver has allowed, if any. For more information, see [Roles and permissions](https://developers.google.com/workspace/drive/api/guides/ref-roles). Note: This field is required for the `ACCEPT` action.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"view\": {\n      \"description\": \"Optional. Indicates the view for this access proposal. This should only be set when the proposal belongs to a view. Only `published` is supported.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"Status\": {\n    \"description\": \"The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors).\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"details\": {\n      \"description\": \"A list of messages that carry the error details. There is a common set of message types for APIs to use.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"object\",\n       \"additionalProperties\": {\n        \"description\": \"Properties of the object. Contains field @type with type URL.\"\n       }\n      }\n     },\n     \"code\": {\n      \"description\": \"The status code, which should be an enum value of google.rpc.Code.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     },\n     \"message\": {\n      \"description\": \"A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the google.rpc.Status.details field, or localized by the client.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"ApproveApprovalRequest\": {\n    \"description\": \"Request for approving an approval as a reviewer.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"message\": {\n      \"description\": \"Optional. A message to accompany the reviewer response on the approval. This message is included in notifications for the action and in the approval activity log.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"AppList\": {\n    \"description\": \"A list of third-party applications which the user has installed or given access to Google Drive.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"items\": {\n      \"description\": \"The list of apps.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/App\"\n      }\n     },\n     \"selfLink\": {\n      \"description\": \"A link back to this list.\",\n      \"type\": \"string\"\n     },\n     \"kind\": {\n      \"description\": \"Output only. Identifies what kind of resource this is. Value: the fixed string \\\"drive#appList\\\".\",\n      \"type\": \"string\"\n     },\n     \"defaultAppIds\": {\n      \"description\": \"The list of app IDs that the user has specified to use by default. The list is in reverse-priority order (lowest to highest).\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     }\n    }\n   },\n   \"LabelModification\": {\n    \"description\": \"A modification to a label on a file. A `LabelModification` can be used to apply a label to a file, update an existing label on a file, or remove a label from a file.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"fieldModifications\": {\n      \"description\": \"The list of modifications to this label's fields.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/LabelFieldModification\"\n      }\n     },\n     \"kind\": {\n      \"description\": \"This is always `\\\"drive#labelModification\\\"`.\",\n      \"type\": \"string\"\n     },\n     \"labelId\": {\n      \"description\": \"The ID of the label to modify.\",\n      \"type\": \"string\"\n     },\n     \"removeLabel\": {\n      \"description\": \"If true, the label will be removed from the file.\",\n      \"type\": \"boolean\"\n     }\n    }\n   },\n   \"User\": {\n    \"description\": \"Information about a Drive user.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"permissionId\": {\n      \"description\": \"Output only. The user's ID as visible in Permission resources.\",\n      \"type\": \"string\"\n     },\n     \"displayName\": {\n      \"description\": \"Output only. A plain text displayable name for this user.\",\n      \"type\": \"string\"\n     },\n     \"me\": {\n      \"description\": \"Output only. Whether this user is the requesting user.\",\n      \"type\": \"boolean\"\n     },\n     \"emailAddress\": {\n      \"description\": \"Output only. The email address of the user. This may not be present in certain contexts if the user has not made their email address visible to the requester.\",\n      \"type\": \"string\"\n     },\n     \"photoLink\": {\n      \"description\": \"Output only. A link to the user's profile photo, if available.\",\n      \"type\": \"string\"\n     },\n     \"kind\": {\n      \"description\": \"Output only. Identifies what kind of resource this is. Value: the fixed string `drive#user`.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"AccessProposal\": {\n    \"description\": \"Manage outstanding access proposals on a file.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"rolesAndViews\": {\n      \"description\": \"A wrapper for the role and view of an access proposal. For more information, see [Roles and permissions](https://developers.google.com/workspace/drive/api/guides/ref-roles).\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/AccessProposalRoleAndView\"\n      }\n     },\n     \"recipientEmailAddress\": {\n      \"description\": \"The email address of the user that will receive permissions, if accepted.\",\n      \"type\": \"string\"\n     },\n     \"requestMessage\": {\n      \"description\": \"The message that the requester added to the proposal.\",\n      \"type\": \"string\"\n     },\n     \"proposalId\": {\n      \"description\": \"The ID of the access proposal.\",\n      \"type\": \"string\"\n     },\n     \"createTime\": {\n      \"description\": \"The creation time.\",\n      \"type\": \"string\",\n      \"format\": \"google-datetime\"\n     },\n     \"fileId\": {\n      \"description\": \"The file ID that the proposal for access is on.\",\n      \"type\": \"string\"\n     },\n     \"requesterEmailAddress\": {\n      \"description\": \"The email address of the requesting user.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"Drive\": {\n    \"description\": \"Representation of a shared drive. Some resource methods (such as `drives.update`) require a `driveId`. Use the `drives.list` method to retrieve the ID for a shared drive.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"name\": {\n      \"description\": \"The name of this shared drive.\",\n      \"type\": \"string\"\n     },\n     \"capabilities\": {\n      \"description\": \"Output only. Capabilities the current user has on this shared drive.\",\n      \"type\": \"object\",\n      \"properties\": {\n       \"canListChildren\": {\n        \"description\": \"Output only. Whether the current user can list the children of folders in this shared drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canShare\": {\n        \"description\": \"Output only. Whether the current user can share files or folders in this shared drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canRename\": {\n        \"description\": \"Output only. Whether the current user can rename files or folders in this shared drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canChangeCopyRequiresWriterPermissionRestriction\": {\n        \"description\": \"Output only. Whether the current user can change the `copyRequiresWriterPermission` restriction of this shared drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canChangeSharingFoldersRequiresOrganizerPermissionRestriction\": {\n        \"description\": \"Output only. Whether the current user can change the `sharingFoldersRequiresOrganizerPermission` restriction of this shared drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canReadRevisions\": {\n        \"description\": \"Output only. Whether the current user can read the revisions resource of files in this shared drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canTrashChildren\": {\n        \"description\": \"Output only. Whether the current user can trash children from folders in this shared drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canComment\": {\n        \"description\": \"Output only. Whether the current user can comment on files in this shared drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canResetDriveRestrictions\": {\n        \"description\": \"Output only. Whether the current user can reset the shared drive restrictions to defaults.\",\n        \"type\": \"boolean\"\n       },\n       \"canChangeDriveBackground\": {\n        \"description\": \"Output only. Whether the current user can change the background of this shared drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canChangeDownloadRestriction\": {\n        \"description\": \"Output only. Whether the current user can change organizer-applied download restrictions of this shared drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canCopy\": {\n        \"description\": \"Output only. Whether the current user can copy files in this shared drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canDeleteDrive\": {\n        \"description\": \"Output only. Whether the current user can delete this shared drive. Attempting to delete the shared drive may still fail if there are untrashed items inside the shared drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canDeleteChildren\": {\n        \"description\": \"Output only. Whether the current user can delete children from folders in this shared drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canChangeDriveMembersOnlyRestriction\": {\n        \"description\": \"Output only. Whether the current user can change the `driveMembersOnly` restriction of this shared drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canDownload\": {\n        \"description\": \"Output only. Whether the current user can download files in this shared drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canAddChildren\": {\n        \"description\": \"Output only. Whether the current user can add children to folders in this shared drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canRenameDrive\": {\n        \"description\": \"Output only. Whether the current user can rename this shared drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canChangeDomainUsersOnlyRestriction\": {\n        \"description\": \"Output only. Whether the current user can change the `domainUsersOnly` restriction of this shared drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canManageMembers\": {\n        \"description\": \"Output only. Whether the current user can add members to this shared drive or remove them or change their role.\",\n        \"type\": \"boolean\"\n       },\n       \"canEdit\": {\n        \"description\": \"Output only. Whether the current user can edit files in this shared drive\",\n        \"type\": \"boolean\"\n       }\n      }\n     },\n     \"themeId\": {\n      \"description\": \"The ID of the theme from which the background image and color will be set. The set of possible `driveThemes` can be retrieved from a `drive.about.get` response. When not specified on a `drive.drives.create` request, a random theme is chosen from which the background image and color are set. This is a write-only field; it can only be set on requests that don't set `colorRgb` or `backgroundImageFile`.\",\n      \"type\": \"string\"\n     },\n     \"id\": {\n      \"description\": \"Output only. The ID of this shared drive which is also the ID of the top level folder of this shared drive.\",\n      \"type\": \"string\"\n     },\n     \"orgUnitId\": {\n      \"description\": \"Output only. The organizational unit of this shared drive. This field is only populated on `drives.list` responses when the `useDomainAdminAccess` parameter is set to `true`.\",\n      \"type\": \"string\"\n     },\n     \"colorRgb\": {\n      \"description\": \"The color of this shared drive as an RGB hex string. It can only be set on a `drive.drives.update` request that does not set `themeId`.\",\n      \"type\": \"string\"\n     },\n     \"createdTime\": {\n      \"description\": \"The time at which the shared drive was created (RFC 3339 date-time).\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     },\n     \"backgroundImageFile\": {\n      \"description\": \"An image file and cropping parameters from which a background image for this shared drive is set. This is a write only field; it can only be set on `drive.drives.update` requests that don't set `themeId`. When specified, all fields of the `backgroundImageFile` must be set.\",\n      \"type\": \"object\",\n      \"properties\": {\n       \"yCoordinate\": {\n        \"description\": \"The Y coordinate of the upper left corner of the cropping area in the background image. This is a value in the closed range of 0 to 1. This value represents the vertical distance from the top side of the entire image to the top side of the cropping area divided by the height of the entire image.\",\n        \"type\": \"number\",\n        \"format\": \"float\"\n       },\n       \"id\": {\n        \"description\": \"The ID of an image file in Google Drive to use for the background image.\",\n        \"type\": \"string\"\n       },\n       \"width\": {\n        \"description\": \"The width of the cropped image in the closed range of 0 to 1. This value represents the width of the cropped image divided by the width of the entire image. The height is computed by applying a width to height aspect ratio of 80 to 9. The resulting image must be at least 1280 pixels wide and 144 pixels high.\",\n        \"type\": \"number\",\n        \"format\": \"float\"\n       },\n       \"xCoordinate\": {\n        \"description\": \"The X coordinate of the upper left corner of the cropping area in the background image. This is a value in the closed range of 0 to 1. This value represents the horizontal distance from the left side of the entire image to the left side of the cropping area divided by the width of the entire image.\",\n        \"type\": \"number\",\n        \"format\": \"float\"\n       }\n      }\n     },\n     \"backgroundImageLink\": {\n      \"description\": \"Output only. A short-lived link to this shared drive's background image.\",\n      \"type\": \"string\"\n     },\n     \"restrictions\": {\n      \"description\": \"A set of restrictions that apply to this shared drive or items inside this shared drive. Note that restrictions can't be set when creating a shared drive. To add a restriction, first create a shared drive and then use `drives.update` to add restrictions.\",\n      \"type\": \"object\",\n      \"properties\": {\n       \"copyRequiresWriterPermission\": {\n        \"description\": \"Whether the options to copy, print, or download files inside this shared drive, should be disabled for readers and commenters. When this restriction is set to `true`, it will override the similarly named field to `true` for any file inside this shared drive.\",\n        \"type\": \"boolean\"\n       },\n       \"adminManagedRestrictions\": {\n        \"description\": \"Whether administrative privileges on this shared drive are required to modify restrictions.\",\n        \"type\": \"boolean\"\n       },\n       \"domainUsersOnly\": {\n        \"description\": \"Whether access to this shared drive and items inside this shared drive is restricted to users of the domain to which this shared drive belongs. This restriction may be overridden by other sharing policies controlled outside of this shared drive.\",\n        \"type\": \"boolean\"\n       },\n       \"downloadRestriction\": {\n        \"$ref\": \"#/components/schemas/DownloadRestriction\"\n       },\n       \"driveMembersOnly\": {\n        \"description\": \"Whether access to items inside this shared drive is restricted to its members.\",\n        \"type\": \"boolean\"\n       },\n       \"sharingFoldersRequiresOrganizerPermission\": {\n        \"description\": \"If true, only users with the organizer role can share folders. If false, users with either the organizer role or the file organizer role can share folders.\",\n        \"type\": \"boolean\"\n       }\n      }\n     },\n     \"kind\": {\n      \"description\": \"Output only. Identifies what kind of resource this is. Value: the fixed string `\\\"drive#drive\\\"`.\",\n      \"type\": \"string\"\n     },\n     \"hidden\": {\n      \"description\": \"Whether the shared drive is hidden from default view.\",\n      \"type\": \"boolean\"\n     }\n    }\n   },\n   \"DeclineApprovalRequest\": {\n    \"description\": \"Request for declining an approval as a reviewer.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"message\": {\n      \"description\": \"Optional. A message to accompany the reviewer response on the approval. This message is included in notifications for the action and in the approval activity log.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"Reply\": {\n    \"description\": \"A reply to a comment on a file. Some resource methods (such as `replies.update`) require a `replyId`. Use the `replies.list` method to retrieve the ID for a reply.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"modifiedTime\": {\n      \"description\": \"The last time the reply was modified (RFC 3339 date-time).\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     },\n     \"deleted\": {\n      \"description\": \"Output only. Whether the reply has been deleted. A deleted reply has no content.\",\n      \"type\": \"boolean\"\n     },\n     \"htmlContent\": {\n      \"description\": \"Output only. The content of the reply with HTML formatting.\",\n      \"type\": \"string\"\n     },\n     \"id\": {\n      \"description\": \"Output only. The ID of the reply.\",\n      \"type\": \"string\"\n     },\n     \"content\": {\n      \"description\": \"The plain text content of the reply. This field is used for setting the content, while `htmlContent` should be displayed. This field is required by the `create` method if no `action` value is specified.\",\n      \"type\": \"string\"\n     },\n     \"author\": {\n      \"$ref\": \"#/components/schemas/User\"\n     },\n     \"createdTime\": {\n      \"description\": \"The time at which the reply was created (RFC 3339 date-time).\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     },\n     \"mentionedEmailAddresses\": {\n      \"description\": \"Output only. A list of email addresses for users mentioned in this comment. If no users are mentioned, the list is empty.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"assigneeEmailAddress\": {\n      \"description\": \"Output only. The email address of the user assigned to this comment. If no user is assigned, the field is unset.\",\n      \"type\": \"string\"\n     },\n     \"kind\": {\n      \"description\": \"Output only. Identifies what kind of resource this is. Value: the fixed string `\\\"drive#reply\\\"`.\",\n      \"type\": \"string\"\n     },\n     \"action\": {\n      \"description\": \"The action the reply performed to the parent comment. The supported values are: * `resolve` * `reopen`\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"ReviewerResponse\": {\n    \"description\": \"A response on an approval made by a specific reviewer.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"response\": {\n      \"description\": \"A reviewer’s response for the approval.\",\n      \"type\": \"string\",\n      \"enum\": [\n       \"RESPONSE_UNSPECIFIED\",\n       \"NO_RESPONSE\",\n       \"APPROVED\",\n       \"DECLINED\"\n      ]\n     },\n     \"kind\": {\n      \"description\": \"This is always drive#reviewerResponse.\",\n      \"type\": \"string\"\n     },\n     \"reviewer\": {\n      \"$ref\": \"#/components/schemas/User\"\n     }\n    }\n   },\n   \"LabelList\": {\n    \"description\": \"A list of labels applied to a file.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"labels\": {\n      \"description\": \"The list of labels.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Label\"\n      }\n     },\n     \"nextPageToken\": {\n      \"description\": \"The page token for the next page of labels. This field will be absent if the end of the list has been reached. If the token is rejected for any reason, it should be discarded, and pagination should be restarted from the first page of results. The page token is typically valid for several hours. However, if new items are added or removed, your expected results might differ.\",\n      \"type\": \"string\"\n     },\n     \"kind\": {\n      \"description\": \"This is always `\\\"drive#labelList\\\"`.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"ModifyLabelsRequest\": {\n    \"description\": \"A request to modify the set of labels on a file. This request may contain many modifications that will either all succeed or all fail atomically.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"labelModifications\": {\n      \"description\": \"The list of modifications to apply to the labels on the file.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/LabelModification\"\n      }\n     },\n     \"kind\": {\n      \"description\": \"This is always `\\\"drive#modifyLabelsRequest\\\"`.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"FileList\": {\n    \"description\": \"A list of files.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"files\": {\n      \"description\": \"The list of files. If `nextPageToken` is populated, then this list may be incomplete and an additional page of results should be fetched.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/File\"\n      }\n     },\n     \"incompleteSearch\": {\n      \"description\": \"Whether the search process was incomplete. If true, then some search results might be missing, since all documents were not searched. This can occur when searching multiple drives with the `allDrives` corpora, but all corpora couldn't be searched. When this happens, it's suggested that clients narrow their query by choosing a different corpus such as `user` or `drive`.\",\n      \"type\": \"boolean\"\n     },\n     \"nextPageToken\": {\n      \"description\": \"The page token for the next page of files. This will be absent if the end of the files list has been reached. If the token is rejected for any reason, it should be discarded, and pagination should be restarted from the first page of results. The page token is typically valid for several hours. However, if new items are added or removed, your expected results might differ.\",\n      \"type\": \"string\"\n     },\n     \"kind\": {\n      \"description\": \"Identifies what kind of resource this is. Value: the fixed string `\\\"drive#fileList\\\"`.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"StartPageToken\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"kind\": {\n      \"description\": \"Identifies what kind of resource this is. Value: the fixed string `\\\"drive#startPageToken\\\"`.\",\n      \"type\": \"string\"\n     },\n     \"startPageToken\": {\n      \"description\": \"The starting page token for listing future changes. The page token doesn't expire.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"RevisionList\": {\n    \"description\": \"A list of revisions of a file.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"revisions\": {\n      \"description\": \"The list of revisions. If nextPageToken is populated, then this list may be incomplete and an additional page of results should be fetched.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Revision\"\n      }\n     },\n     \"kind\": {\n      \"description\": \"Identifies what kind of resource this is. Value: the fixed string `\\\"drive#revisionList\\\"`.\",\n      \"type\": \"string\"\n     },\n     \"nextPageToken\": {\n      \"description\": \"The page token for the next page of revisions. This will be absent if the end of the revisions list has been reached. If the token is rejected for any reason, it should be discarded, and pagination should be restarted from the first page of results. The page token is typically valid for several hours. However, if new items are added or removed, your expected results might differ.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"ListAccessProposalsResponse\": {\n    \"description\": \"The response to an access proposal list request.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"nextPageToken\": {\n      \"description\": \"The continuation token for the next page of results. This will be absent if the end of the results list has been reached. If the token is rejected for any reason, it should be discarded, and pagination should be restarted from the first page of results.\",\n      \"type\": \"string\"\n     },\n     \"accessProposals\": {\n      \"description\": \"The list of access proposals. This field is only populated in Drive API v3.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/AccessProposal\"\n      }\n     }\n    }\n   },\n   \"DownloadRestrictionsMetadata\": {\n    \"description\": \"Download restrictions applied to the file.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"itemDownloadRestriction\": {\n      \"$ref\": \"#/components/schemas/DownloadRestriction\"\n     },\n     \"effectiveDownloadRestrictionWithContext\": {\n      \"$ref\": \"#/components/schemas/DownloadRestriction\"\n     }\n    }\n   },\n   \"TeamDriveList\": {\n    \"description\": \"A list of Team Drives.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"kind\": {\n      \"description\": \"Identifies what kind of resource this is. Value: the fixed string `\\\"drive#teamDriveList\\\"`.\",\n      \"type\": \"string\"\n     },\n     \"teamDrives\": {\n      \"description\": \"The list of Team Drives. If nextPageToken is populated, then this list may be incomplete and an additional page of results should be fetched.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/TeamDrive\"\n      }\n     },\n     \"nextPageToken\": {\n      \"description\": \"The page token for the next page of Team Drives. This will be absent if the end of the Team Drives list has been reached. If the token is rejected for any reason, it should be discarded, and pagination should be restarted from the first page of results. The page token is typically valid for several hours. However, if new items are added or removed, your expected results might differ.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"Operation\": {\n    \"description\": \"This resource represents a long-running operation that is the result of a network API call.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"name\": {\n      \"description\": \"The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`.\",\n      \"type\": \"string\"\n     },\n     \"metadata\": {\n      \"description\": \"Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any.\",\n      \"type\": \"object\",\n      \"additionalProperties\": {\n       \"description\": \"Properties of the object. Contains field @type with type URL.\"\n      }\n     },\n     \"done\": {\n      \"description\": \"If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available.\",\n      \"type\": \"boolean\"\n     },\n     \"error\": {\n      \"$ref\": \"#/components/schemas/Status\"\n     },\n     \"response\": {\n      \"description\": \"The normal, successful response of the operation. If the original method returns no data on success, such as `Delete`, the response is `google.protobuf.Empty`. If the original method is standard `Get`/`Create`/`Update`, the response should be the resource. For other methods, the response should have the type `XxxResponse`, where `Xxx` is the original method name. For example, if the original method name is `TakeSnapshot()`, the inferred response type is `TakeSnapshotResponse`.\",\n      \"type\": \"object\",\n      \"additionalProperties\": {\n       \"description\": \"Properties of the object. Contains field @type with type URL.\"\n      }\n     }\n    }\n   },\n   \"GeneratedIds\": {\n    \"description\": \"A list of generated file IDs which can be provided in create requests.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"ids\": {\n      \"description\": \"The IDs generated for the requesting user in the specified space.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"kind\": {\n      \"description\": \"Identifies what kind of resource this is. Value: the fixed string `\\\"drive#generatedIds\\\"`.\",\n      \"type\": \"string\"\n     },\n     \"space\": {\n      \"description\": \"The type of file that can be created with these IDs.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"StartApprovalRequest\": {\n    \"description\": \"Allows creating an approval on a file.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"reviewerEmails\": {\n      \"description\": \"Required. The emails of the users who are set to review the approval.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"lockFile\": {\n      \"description\": \"Optional. Whether to lock the file when starting the approval.\",\n      \"type\": \"boolean\"\n     },\n     \"fileContentChangeBehavior\": {\n      \"description\": \"Optional. The behavior of the approval when the file content changes.\",\n      \"type\": \"string\",\n      \"enum\": [\n       \"FILE_CONTENT_CHANGE_BEHAVIOR_UNSPECIFIED\",\n       \"RESET_APPROVAL\",\n       \"NO_APPROVAL_ACTION\"\n      ]\n     },\n     \"dueTime\": {\n      \"description\": \"Optional. The time that the approval is due.\",\n      \"type\": \"string\",\n      \"format\": \"google-datetime\"\n     },\n     \"message\": {\n      \"description\": \"Optional. A message to send to reviewers when notifying them of the approval request.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"CommentList\": {\n    \"description\": \"A list of comments on a file.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"comments\": {\n      \"description\": \"The list of comments. If nextPageToken is populated, then this list may be incomplete and an additional page of results should be fetched.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Comment\"\n      }\n     },\n     \"kind\": {\n      \"description\": \"Identifies what kind of resource this is. Value: the fixed string `\\\"drive#commentList\\\"`.\",\n      \"type\": \"string\"\n     },\n     \"nextPageToken\": {\n      \"description\": \"The page token for the next page of comments. This will be absent if the end of the comments list has been reached. If the token is rejected for any reason, it should be discarded, and pagination should be restarted from the first page of results. The page token is typically valid for several hours. However, if new items are added or removed, your expected results might differ.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"AppIcons\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"size\": {\n      \"description\": \"Size of the icon. Represented as the maximum of the width and height.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     },\n     \"iconUrl\": {\n      \"description\": \"URL for the icon.\",\n      \"type\": \"string\"\n     },\n     \"category\": {\n      \"description\": \"Category of the icon. Allowed values are: * `application` - The icon for the application. * `document` - The icon for a file associated with the app. * `documentShared` - The icon for a shared file associated with the app.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"ModifyLabelsResponse\": {\n    \"description\": \"Response to a `ModifyLabels` request. This contains only those labels which were added or updated by the request.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"modifiedLabels\": {\n      \"description\": \"The list of labels which were added or updated by the request.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Label\"\n      }\n     },\n     \"kind\": {\n      \"description\": \"This is always `\\\"drive#modifyLabelsResponse\\\"`.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"LabelField\": {\n    \"description\": \"Representation of field, which is a typed key-value pair.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"selection\": {\n      \"description\": \"Only present if `valueType` is `selection`\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"user\": {\n      \"description\": \"Only present if `valueType` is `user`.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/User\"\n      }\n     },\n     \"text\": {\n      \"description\": \"Only present if `valueType` is `text`.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"valueType\": {\n      \"description\": \"The field type. While new values may be supported in the future, the following are currently allowed: * `dateString` * `integer` * `selection` * `text` * `user`\",\n      \"type\": \"string\"\n     },\n     \"integer\": {\n      \"description\": \"Only present if `valueType` is `integer`.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\",\n       \"format\": \"int64\"\n      }\n     },\n     \"kind\": {\n      \"description\": \"This is always drive#labelField.\",\n      \"type\": \"string\"\n     },\n     \"id\": {\n      \"description\": \"The identifier of this label field.\",\n      \"type\": \"string\"\n     },\n     \"dateString\": {\n      \"description\": \"Only present if valueType is dateString. RFC 3339 formatted date: YYYY-MM-DD.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\",\n       \"format\": \"date\"\n      }\n     }\n    }\n   },\n   \"Comment\": {\n    \"description\": \"A comment on a file. Some resource methods (such as `comments.update`) require a `commentId`. Use the `comments.list` method to retrieve the ID for a comment in a file.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"content\": {\n      \"description\": \"The plain text content of the comment. This field is used for setting the content, while `htmlContent` should be displayed.\",\n      \"type\": \"string\"\n     },\n     \"createdTime\": {\n      \"description\": \"The time at which the comment was created (RFC 3339 date-time).\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     },\n     \"id\": {\n      \"description\": \"Output only. The ID of the comment.\",\n      \"type\": \"string\"\n     },\n     \"modifiedTime\": {\n      \"description\": \"The last time the comment or any of its replies was modified (RFC 3339 date-time).\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     },\n     \"htmlContent\": {\n      \"description\": \"Output only. The content of the comment with HTML formatting.\",\n      \"type\": \"string\"\n     },\n     \"resolved\": {\n      \"description\": \"Output only. Whether the comment has been resolved by one of its replies.\",\n      \"type\": \"boolean\"\n     },\n     \"deleted\": {\n      \"description\": \"Output only. Whether the comment has been deleted. A deleted comment has no content.\",\n      \"type\": \"boolean\"\n     },\n     \"mentionedEmailAddresses\": {\n      \"description\": \"Output only. A list of email addresses for users mentioned in this comment. If no users are mentioned, the list is empty.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"author\": {\n      \"$ref\": \"#/components/schemas/User\"\n     },\n     \"anchor\": {\n      \"description\": \"A region of the document represented as a JSON string. For details on defining anchor properties, refer to [Manage comments and replies](https://developers.google.com/workspace/drive/api/v3/manage-comments).\",\n      \"type\": \"string\"\n     },\n     \"assigneeEmailAddress\": {\n      \"description\": \"Output only. The email address of the user assigned to this comment. If no user is assigned, the field is unset.\",\n      \"type\": \"string\"\n     },\n     \"kind\": {\n      \"description\": \"Output only. Identifies what kind of resource this is. Value: the fixed string `\\\"drive#comment\\\"`.\",\n      \"type\": \"string\"\n     },\n     \"quotedFileContent\": {\n      \"description\": \"The file content to which the comment refers, typically within the anchor region. For a text file, for example, this would be the text at the location of the comment.\",\n      \"type\": \"object\",\n      \"properties\": {\n       \"value\": {\n        \"description\": \"The quoted content itself. This is interpreted as plain text if set through the API.\",\n        \"type\": \"string\"\n       },\n       \"mimeType\": {\n        \"description\": \"The MIME type of the quoted content.\",\n        \"type\": \"string\"\n       }\n      }\n     },\n     \"replies\": {\n      \"description\": \"Output only. The full list of replies to the comment in chronological order.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Reply\"\n      }\n     }\n    }\n   },\n   \"DownloadRestriction\": {\n    \"description\": \"A restriction for copy and download of the file.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"restrictedForReaders\": {\n      \"description\": \"Whether download and copy is restricted for readers.\",\n      \"type\": \"boolean\"\n     },\n     \"restrictedForWriters\": {\n      \"description\": \"Whether download and copy is restricted for writers. If true, download is also restricted for readers.\",\n      \"type\": \"boolean\"\n     }\n    }\n   },\n   \"File\": {\n    \"description\": \"The metadata for a file. Some resource methods (such as `files.update`) require a `fileId`. Use the `files.list` method to retrieve the ID for a file.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"sha1Checksum\": {\n      \"description\": \"Output only. The SHA1 checksum associated with this file, if available. This field is only populated for files with content stored in Google Drive; it's not populated for Docs Editors or shortcut files.\",\n      \"type\": \"string\"\n     },\n     \"trashed\": {\n      \"description\": \"Whether the file has been trashed, either explicitly or from a trashed parent folder. Only the owner may trash a file, but other users can still access the file in the owner's trash until it's permanently deleted.\",\n      \"type\": \"boolean\"\n     },\n     \"thumbnailLink\": {\n      \"description\": \"Output only. A short-lived link to the file's thumbnail, if available. Typically lasts on the order of hours. Not intended for direct usage on web applications due to [Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) policies. Consider using a proxy server. Only populated when the requesting app can access the file's content. If the file isn't shared publicly, the URL returned in `files.thumbnailLink` must be fetched using a credentialed request.\",\n      \"type\": \"string\"\n     },\n     \"explicitlyTrashed\": {\n      \"description\": \"Output only. Whether the file has been explicitly trashed, as opposed to recursively trashed from a parent folder.\",\n      \"type\": \"boolean\"\n     },\n     \"sha256Checksum\": {\n      \"description\": \"Output only. The SHA256 checksum associated with this file, if available. This field is only populated for files with content stored in Google Drive; it's not populated for Docs Editors or shortcut files.\",\n      \"type\": \"string\"\n     },\n     \"modifiedTime\": {\n      \"description\": \"he last time the file was modified by anyone (RFC 3339 date-time). Note that setting modifiedTime will also update modifiedByMeTime for the user.\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     },\n     \"owners\": {\n      \"description\": \"Output only. The owner of this file. Only certain legacy files may have more than one owner. This field isn't populated for items in shared drives.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/User\"\n      }\n     },\n     \"labelInfo\": {\n      \"description\": \"Label information on the file.\",\n      \"type\": \"object\",\n      \"properties\": {\n       \"labels\": {\n        \"description\": \"Output only. The set of labels on the file as requested by the label IDs in the `includeLabels` parameter. By default, no labels are returned.\",\n        \"type\": \"array\",\n        \"items\": {\n         \"$ref\": \"#/components/schemas/Label\"\n        }\n       }\n      }\n     },\n     \"quotaBytesUsed\": {\n      \"description\": \"Output only. The number of storage quota bytes used by the file. This includes the head revision as well as previous revisions with `keepForever` enabled.\",\n      \"type\": \"string\",\n      \"format\": \"int64\"\n     },\n     \"originalFilename\": {\n      \"description\": \"The original filename of the uploaded content if available, or else the original value of the `name` field. This is only available for files with binary content in Google Drive.\",\n      \"type\": \"string\"\n     },\n     \"downloadRestrictions\": {\n      \"$ref\": \"#/components/schemas/DownloadRestrictionsMetadata\"\n     },\n     \"description\": {\n      \"description\": \"A short description of the file.\",\n      \"type\": \"string\"\n     },\n     \"hasThumbnail\": {\n      \"description\": \"Output only. Whether this file has a thumbnail. This doesn't indicate whether the requesting app has access to the thumbnail. To check access, look for the presence of the thumbnailLink field.\",\n      \"type\": \"boolean\"\n     },\n     \"imageMediaMetadata\": {\n      \"description\": \"Output only. Additional metadata about image media, if available.\",\n      \"type\": \"object\",\n      \"properties\": {\n       \"focalLength\": {\n        \"description\": \"Output only. The focal length used to create the photo, in millimeters.\",\n        \"type\": \"number\",\n        \"format\": \"float\"\n       },\n       \"rotation\": {\n        \"description\": \"Output only. The number of clockwise 90 degree rotations applied from the image's original orientation.\",\n        \"type\": \"integer\",\n        \"format\": \"int32\"\n       },\n       \"flashUsed\": {\n        \"description\": \"Output only. Whether a flash was used to create the photo.\",\n        \"type\": \"boolean\"\n       },\n       \"exposureTime\": {\n        \"description\": \"Output only. The length of the exposure, in seconds.\",\n        \"type\": \"number\",\n        \"format\": \"float\"\n       },\n       \"aperture\": {\n        \"description\": \"Output only. The aperture used to create the photo (f-number).\",\n        \"type\": \"number\",\n        \"format\": \"float\"\n       },\n       \"maxApertureValue\": {\n        \"description\": \"Output only. The smallest f-number of the lens at the focal length used to create the photo (APEX value).\",\n        \"type\": \"number\",\n        \"format\": \"float\"\n       },\n       \"exposureBias\": {\n        \"description\": \"Output only. The exposure bias of the photo (APEX value).\",\n        \"type\": \"number\",\n        \"format\": \"float\"\n       },\n       \"sensor\": {\n        \"description\": \"Output only. The type of sensor used to create the photo.\",\n        \"type\": \"string\"\n       },\n       \"isoSpeed\": {\n        \"description\": \"Output only. The ISO speed used to create the photo.\",\n        \"type\": \"integer\",\n        \"format\": \"int32\"\n       },\n       \"location\": {\n        \"description\": \"Output only. Geographic location information stored in the image.\",\n        \"type\": \"object\",\n        \"properties\": {\n         \"longitude\": {\n          \"description\": \"Output only. The longitude stored in the image.\",\n          \"type\": \"number\",\n          \"format\": \"double\"\n         },\n         \"latitude\": {\n          \"description\": \"Output only. The latitude stored in the image.\",\n          \"type\": \"number\",\n          \"format\": \"double\"\n         },\n         \"altitude\": {\n          \"description\": \"Output only. The altitude stored in the image.\",\n          \"type\": \"number\",\n          \"format\": \"double\"\n         }\n        }\n       },\n       \"whiteBalance\": {\n        \"description\": \"Output only. The white balance mode used to create the photo.\",\n        \"type\": \"string\"\n       },\n       \"cameraModel\": {\n        \"description\": \"Output only. The model of the camera used to create the photo.\",\n        \"type\": \"string\"\n       },\n       \"cameraMake\": {\n        \"description\": \"Output only. The make of the camera used to create the photo.\",\n        \"type\": \"string\"\n       },\n       \"time\": {\n        \"description\": \"Output only. The date and time the photo was taken (EXIF DateTime).\",\n        \"type\": \"string\"\n       },\n       \"exposureMode\": {\n        \"description\": \"Output only. The exposure mode used to create the photo.\",\n        \"type\": \"string\"\n       },\n       \"meteringMode\": {\n        \"description\": \"Output only. The metering mode used to create the photo.\",\n        \"type\": \"string\"\n       },\n       \"height\": {\n        \"description\": \"Output only. The height of the image in pixels.\",\n        \"type\": \"integer\",\n        \"format\": \"int32\"\n       },\n       \"lens\": {\n        \"description\": \"Output only. The lens used to create the photo.\",\n        \"type\": \"string\"\n       },\n       \"colorSpace\": {\n        \"description\": \"Output only. The color space of the photo.\",\n        \"type\": \"string\"\n       },\n       \"width\": {\n        \"description\": \"Output only. The width of the image in pixels.\",\n        \"type\": \"integer\",\n        \"format\": \"int32\"\n       },\n       \"subjectDistance\": {\n        \"description\": \"Output only. The distance to the subject of the photo, in meters.\",\n        \"type\": \"integer\",\n        \"format\": \"int32\"\n       }\n      }\n     },\n     \"contentHints\": {\n      \"description\": \"Additional information about the content of the file. These fields are never populated in responses.\",\n      \"type\": \"object\",\n      \"properties\": {\n       \"indexableText\": {\n        \"description\": \"Text to be indexed for the file to improve fullText queries. This is limited to 128 KB in length and may contain HTML elements.\",\n        \"type\": \"string\"\n       },\n       \"thumbnail\": {\n        \"description\": \"A thumbnail for the file. This will only be used if Google Drive cannot generate a standard thumbnail.\",\n        \"type\": \"object\",\n        \"properties\": {\n         \"image\": {\n          \"description\": \"The thumbnail data encoded with URL-safe Base64 ([RFC 4648 section 5](https://datatracker.ietf.org/doc/html/rfc4648#section-5)).\",\n          \"type\": \"string\",\n          \"format\": \"byte\"\n         },\n         \"mimeType\": {\n          \"description\": \"The MIME type of the thumbnail.\",\n          \"type\": \"string\"\n         }\n        }\n       }\n      }\n     },\n     \"contentRestrictions\": {\n      \"description\": \"Restrictions for accessing the content of the file. Only populated if such a restriction exists.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/ContentRestriction\"\n      }\n     },\n     \"createdTime\": {\n      \"description\": \"The time at which the file was created (RFC 3339 date-time).\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     },\n     \"parents\": {\n      \"description\": \"The ID of the parent folder containing the file. A file can only have one parent folder; specifying multiple parents isn't supported. If not specified as part of a create request, the file is placed directly in the user's My Drive folder. If not specified as part of a copy request, the file inherits any discoverable parent of the source file. Update requests must use the `addParents` and `removeParents` parameters to modify the parents list.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"trashingUser\": {\n      \"$ref\": \"#/components/schemas/User\"\n     },\n     \"sharedWithMeTime\": {\n      \"description\": \"The time at which the file was shared with the user, if applicable (RFC 3339 date-time).\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     },\n     \"trashedTime\": {\n      \"description\": \"The time that the item was trashed (RFC 3339 date-time). Only populated for items in shared drives.\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     },\n     \"shortcutDetails\": {\n      \"description\": \"Information about a shortcut file.\",\n      \"type\": \"object\",\n      \"properties\": {\n       \"targetResourceKey\": {\n        \"description\": \"Output only. The `resourceKey` for the target file.\",\n        \"type\": \"string\"\n       },\n       \"targetMimeType\": {\n        \"description\": \"Output only. The MIME type of the file that this shortcut points to. The value of this field is a snapshot of the target's MIME type, captured when the shortcut is created.\",\n        \"type\": \"string\"\n       },\n       \"targetId\": {\n        \"description\": \"The ID of the file that this shortcut points to. Can only be set on `files.create` requests.\",\n        \"type\": \"string\"\n       }\n      }\n     },\n     \"iconLink\": {\n      \"description\": \"Output only. A static, unauthenticated link to the file's icon.\",\n      \"type\": \"string\"\n     },\n     \"starred\": {\n      \"description\": \"Whether the user has starred the file.\",\n      \"type\": \"boolean\"\n     },\n     \"properties\": {\n      \"description\": \"A collection of arbitrary key-value pairs which are visible to all apps.\\nEntries with null values are cleared in update and copy requests.\",\n      \"type\": \"object\",\n      \"additionalProperties\": {\n       \"type\": \"string\"\n      }\n     },\n     \"lastModifyingUser\": {\n      \"$ref\": \"#/components/schemas/User\"\n     },\n     \"exportLinks\": {\n      \"description\": \"Output only. Links for exporting Docs Editors files to specific formats.\",\n      \"type\": \"object\",\n      \"additionalProperties\": {\n       \"type\": \"string\"\n      }\n     },\n     \"viewedByMe\": {\n      \"description\": \"Output only. Whether the file has been viewed by this user.\",\n      \"type\": \"boolean\"\n     },\n     \"size\": {\n      \"description\": \"Output only. Size in bytes of blobs and Google Workspace editor files. Won't be populated for files that have no size, like shortcuts and folders.\",\n      \"type\": \"string\",\n      \"format\": \"int64\"\n     },\n     \"name\": {\n      \"description\": \"The name of the file. This isn't necessarily unique within a folder. Note that for immutable items such as the top-level folders of shared drives, the My Drive root folder, and the Application Data folder, the name is constant.\",\n      \"type\": \"string\"\n     },\n     \"modifiedByMeTime\": {\n      \"description\": \"The last time the file was modified by the user (RFC 3339 date-time).\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     },\n     \"viewedByMeTime\": {\n      \"description\": \"The last time the file was viewed by the user (RFC 3339 date-time).\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     },\n     \"copyRequiresWriterPermission\": {\n      \"description\": \"Whether the options to copy, print, or download this file should be disabled for readers and commenters.\",\n      \"type\": \"boolean\"\n     },\n     \"sharingUser\": {\n      \"$ref\": \"#/components/schemas/User\"\n     },\n     \"permissions\": {\n      \"description\": \"Output only. The full list of permissions for the file. This is only available if the requesting user can share the file. Not populated for items in shared drives.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Permission\"\n      }\n     },\n     \"writersCanShare\": {\n      \"description\": \"Whether users with only `writer` permission can modify the file's permissions. Not populated for items in shared drives.\",\n      \"type\": \"boolean\"\n     },\n     \"inheritedPermissionsDisabled\": {\n      \"description\": \"Whether this file has inherited permissions disabled. Inherited permissions are enabled by default.\",\n      \"type\": \"boolean\"\n     },\n     \"hasAugmentedPermissions\": {\n      \"description\": \"Output only. Whether there are permissions directly on this file. This field is only populated for items in shared drives.\",\n      \"type\": \"boolean\"\n     },\n     \"modifiedByMe\": {\n      \"description\": \"Output only. Whether the file has been modified by this user.\",\n      \"type\": \"boolean\"\n     },\n     \"shared\": {\n      \"description\": \"Output only. Whether the file has been shared. Not populated for items in shared drives.\",\n      \"type\": \"boolean\"\n     },\n     \"webViewLink\": {\n      \"description\": \"Output only. A link for opening the file in a relevant Google editor or viewer in a browser.\",\n      \"type\": \"string\"\n     },\n     \"viewersCanCopyContent\": {\n      \"description\": \"Deprecated: Use `copyRequiresWriterPermission` instead.\",\n      \"type\": \"boolean\"\n     },\n     \"linkShareMetadata\": {\n      \"description\": \"Contains details about the link URLs that clients are using to refer to this item.\",\n      \"type\": \"object\",\n      \"properties\": {\n       \"securityUpdateEnabled\": {\n        \"description\": \"Output only. Whether the security update is enabled for this file.\",\n        \"type\": \"boolean\"\n       },\n       \"securityUpdateEligible\": {\n        \"description\": \"Output only. Whether the file is eligible for security update.\",\n        \"type\": \"boolean\"\n       }\n      }\n     },\n     \"ownedByMe\": {\n      \"description\": \"Output only. Whether the user owns the file. Not populated for items in shared drives.\",\n      \"type\": \"boolean\"\n     },\n     \"isAppAuthorized\": {\n      \"description\": \"Output only. Whether the file was created or opened by the requesting app.\",\n      \"type\": \"boolean\"\n     },\n     \"videoMediaMetadata\": {\n      \"description\": \"Output only. Additional metadata about video media. This may not be available immediately upon upload.\",\n      \"type\": \"object\",\n      \"properties\": {\n       \"height\": {\n        \"description\": \"Output only. The height of the video in pixels.\",\n        \"type\": \"integer\",\n        \"format\": \"int32\"\n       },\n       \"width\": {\n        \"description\": \"Output only. The width of the video in pixels.\",\n        \"type\": \"integer\",\n        \"format\": \"int32\"\n       },\n       \"durationMillis\": {\n        \"description\": \"Output only. The duration of the video in milliseconds.\",\n        \"type\": \"string\",\n        \"format\": \"int64\"\n       }\n      }\n     },\n     \"spaces\": {\n      \"description\": \"Output only. The list of spaces which contain the file. The currently supported values are `drive`, `appDataFolder`, and `photos`.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"md5Checksum\": {\n      \"description\": \"Output only. The MD5 checksum for the content of the file. This is only applicable to files with binary content in Google Drive.\",\n      \"type\": \"string\"\n     },\n     \"mimeType\": {\n      \"description\": \"The MIME type of the file. Google Drive attempts to automatically detect an appropriate value from uploaded content, if no value is provided. The value cannot be changed unless a new revision is uploaded. If a file is created with a Google Doc MIME type, the uploaded content is imported, if possible. The supported import formats are published in the [`about`](/workspace/drive/api/reference/rest/v3/about) resource.\",\n      \"type\": \"string\"\n     },\n     \"resourceKey\": {\n      \"description\": \"Output only. A key needed to access the item via a shared link.\",\n      \"type\": \"string\"\n     },\n     \"version\": {\n      \"description\": \"Output only. A monotonically increasing version number for the file. This reflects every change made to the file on the server, even those not visible to the user.\",\n      \"type\": \"string\",\n      \"format\": \"int64\"\n     },\n     \"kind\": {\n      \"description\": \"Output only. Identifies what kind of resource this is. Value: the fixed string `\\\"drive#file\\\"`.\",\n      \"type\": \"string\"\n     },\n     \"driveId\": {\n      \"description\": \"Output only. ID of the shared drive the file resides in. Only populated for items in shared drives.\",\n      \"type\": \"string\"\n     },\n     \"clientEncryptionDetails\": {\n      \"$ref\": \"#/components/schemas/ClientEncryptionDetails\"\n     },\n     \"webContentLink\": {\n      \"description\": \"Output only. A link for downloading the content of the file in a browser. This is only available for files with binary content in Google Drive.\",\n      \"type\": \"string\"\n     },\n     \"permissionIds\": {\n      \"description\": \"Output only. List of permission IDs for users with access to this file.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"fileExtension\": {\n      \"description\": \"Output only. The final component of `fullFileExtension`. This is only available for files with binary content in Google Drive.\",\n      \"type\": \"string\"\n     },\n     \"appProperties\": {\n      \"description\": \"A collection of arbitrary key-value pairs which are private to the requesting app.\\nEntries with null values are cleared in update and copy requests. These properties can only be retrieved using an authenticated request. An authenticated request uses an access token obtained with a OAuth 2 client ID. You cannot use an API key to retrieve private properties.\",\n      \"type\": \"object\",\n      \"additionalProperties\": {\n       \"type\": \"string\"\n      }\n     },\n     \"capabilities\": {\n      \"description\": \"Output only. Capabilities the current user has on this file. Each capability corresponds to a fine-grained action that a user may take. For more information, see [Understand file capabilities](https://developers.google.com/workspace/drive/api/guides/manage-sharing#capabilities).\",\n      \"type\": \"object\",\n      \"properties\": {\n       \"canTrash\": {\n        \"description\": \"Output only. Whether the current user can move this file to trash.\",\n        \"type\": \"boolean\"\n       },\n       \"canModifyEditorContentRestriction\": {\n        \"description\": \"Output only. Whether the current user can add or modify content restrictions on the file which are editor restricted.\",\n        \"type\": \"boolean\"\n       },\n       \"canRemoveChildren\": {\n        \"description\": \"Output only. Whether the current user can remove children from this folder. This is always `false` when the item isn't a folder. For a folder in a shared drive, use `canDeleteChildren` or `canTrashChildren` instead.\",\n        \"type\": \"boolean\"\n       },\n       \"canShare\": {\n        \"description\": \"Output only. Whether the current user can modify the sharing settings for this file.\",\n        \"type\": \"boolean\"\n       },\n       \"canMoveChildrenOutOfDrive\": {\n        \"description\": \"Output only. Whether the current user can move children of this folder outside of the shared drive. This is `false` when the item isn't a folder. Only populated for items in shared drives.\",\n        \"type\": \"boolean\"\n       },\n       \"canMoveItemIntoTeamDrive\": {\n        \"description\": \"Deprecated: Output only. Use `canMoveItemOutOfDrive` instead.\",\n        \"type\": \"boolean\"\n       },\n       \"canChangeViewersCanCopyContent\": {\n        \"description\": \"Deprecated: Output only.\",\n        \"type\": \"boolean\"\n       },\n       \"canComment\": {\n        \"description\": \"Output only. Whether the current user can comment on this file.\",\n        \"type\": \"boolean\"\n       },\n       \"canMoveItemOutOfDrive\": {\n        \"description\": \"Output only. Whether the current user can move this item outside of this drive by changing its parent. Note that a request to change the parent of the item may still fail depending on the new parent that's being added.\",\n        \"type\": \"boolean\"\n       },\n       \"canModifyContent\": {\n        \"description\": \"Output only. Whether the current user can modify the content of this file.\",\n        \"type\": \"boolean\"\n       },\n       \"canUntrash\": {\n        \"description\": \"Output only. Whether the current user can restore this file from trash.\",\n        \"type\": \"boolean\"\n       },\n       \"canListChildren\": {\n        \"description\": \"Output only. Whether the current user can list the children of this folder. This is always `false` when the item isn't a folder.\",\n        \"type\": \"boolean\"\n       },\n       \"canReadDrive\": {\n        \"description\": \"Output only. Whether the current user can read the shared drive to which this file belongs. Only populated for items in shared drives.\",\n        \"type\": \"boolean\"\n       },\n       \"canMoveChildrenWithinDrive\": {\n        \"description\": \"Output only. Whether the current user can move children of this folder within this drive. This is `false` when the item isn't a folder. Note that a request to move the child may still fail depending on the current user's access to the child and to the destination folder.\",\n        \"type\": \"boolean\"\n       },\n       \"canReadLabels\": {\n        \"description\": \"Output only. Whether the current user can read the labels on the file.\",\n        \"type\": \"boolean\"\n       },\n       \"canMoveTeamDriveItem\": {\n        \"description\": \"Deprecated: Output only. Use `canMoveItemWithinDrive` or `canMoveItemOutOfDrive` instead.\",\n        \"type\": \"boolean\"\n       },\n       \"canModifyOwnerContentRestriction\": {\n        \"description\": \"Output only. Whether the current user can add or modify content restrictions which are owner restricted.\",\n        \"type\": \"boolean\"\n       },\n       \"canTrashChildren\": {\n        \"description\": \"Output only. Whether the current user can trash children of this folder. This is `false` when the item isn't a folder. Only populated for items in shared drives.\",\n        \"type\": \"boolean\"\n       },\n       \"canReadRevisions\": {\n        \"description\": \"Output only. Whether the current user can read the revisions resource of this file. For a shared drive item, whether revisions of non-folder descendants of this item, or this item if it's not a folder, can be read.\",\n        \"type\": \"boolean\"\n       },\n       \"canRemoveContentRestriction\": {\n        \"description\": \"Output only. Whether there's a content restriction on the file that can be removed by the current user.\",\n        \"type\": \"boolean\"\n       },\n       \"canMoveItemWithinDrive\": {\n        \"description\": \"Output only. Whether the current user can move this item within this drive. Note that a request to change the parent of the item may still fail depending on the new parent that's being added and the parent that is being removed.\",\n        \"type\": \"boolean\"\n       },\n       \"canDeleteChildren\": {\n        \"description\": \"Output only. Whether the current user can delete children of this folder. This is `false` when the item isn't a folder. Only populated for items in shared drives.\",\n        \"type\": \"boolean\"\n       },\n       \"canDelete\": {\n        \"description\": \"Output only. Whether the current user can delete this file.\",\n        \"type\": \"boolean\"\n       },\n       \"canRename\": {\n        \"description\": \"Output only. Whether the current user can rename this file.\",\n        \"type\": \"boolean\"\n       },\n       \"canReadTeamDrive\": {\n        \"description\": \"Deprecated: Output only. Use `canReadDrive` instead.\",\n        \"type\": \"boolean\"\n       },\n       \"canRemoveMyDriveParent\": {\n        \"description\": \"Output only. Whether the current user can remove a parent from the item without adding another parent in the same request. Not populated for shared drive files.\",\n        \"type\": \"boolean\"\n       },\n       \"canDownload\": {\n        \"description\": \"Output only. Whether the current user can download this file.\",\n        \"type\": \"boolean\"\n       },\n       \"canEdit\": {\n        \"description\": \"Output only. Whether the current user can edit this file. Other factors may limit the type of changes a user can make to a file. For example, see `canChangeCopyRequiresWriterPermission` or `canModifyContent`.\",\n        \"type\": \"boolean\"\n       },\n       \"canEnableInheritedPermissions\": {\n        \"description\": \"Whether a user can re-enable inherited permissions.\",\n        \"type\": \"boolean\"\n       },\n       \"canChangeCopyRequiresWriterPermission\": {\n        \"description\": \"Output only. Whether the current user can change the `copyRequiresWriterPermission` restriction of this file.\",\n        \"type\": \"boolean\"\n       },\n       \"canChangeItemDownloadRestriction\": {\n        \"description\": \"Output only. Whether the current user can change the owner or organizer-applied download restrictions of the file.\",\n        \"type\": \"boolean\"\n       },\n       \"canMoveChildrenOutOfTeamDrive\": {\n        \"description\": \"Deprecated: Output only. Use `canMoveChildrenOutOfDrive` instead.\",\n        \"type\": \"boolean\"\n       },\n       \"canModifyContentRestriction\": {\n        \"description\": \"Deprecated: Output only. Use one of `canModifyEditorContentRestriction`, `canModifyOwnerContentRestriction`, or `canRemoveContentRestriction`.\",\n        \"type\": \"boolean\"\n       },\n       \"canAcceptOwnership\": {\n        \"description\": \"Output only. Whether the current user is the pending owner of the file. Not populated for shared drive files.\",\n        \"type\": \"boolean\"\n       },\n       \"canMoveItemOutOfTeamDrive\": {\n        \"description\": \"Deprecated: Output only. Use `canMoveItemOutOfDrive` instead.\",\n        \"type\": \"boolean\"\n       },\n       \"canModifyLabels\": {\n        \"description\": \"Output only. Whether the current user can modify the labels on the file.\",\n        \"type\": \"boolean\"\n       },\n       \"canMoveChildrenWithinTeamDrive\": {\n        \"description\": \"Deprecated: Output only. Use `canMoveChildrenWithinDrive` instead.\",\n        \"type\": \"boolean\"\n       },\n       \"canAccessViaGenAi\": {\n        \"description\": \"Whether the current user can access this file via Gen AI features. For more information, see [Drive MCP file eligibility](https://developers.google.com/workspace/drive/api/guides/drive-mcp-server-file-eligibility).\",\n        \"type\": \"boolean\"\n       },\n       \"canChangeSecurityUpdateEnabled\": {\n        \"description\": \"Output only. Whether the current user can change the `securityUpdateEnabled` field on link share metadata.\",\n        \"type\": \"boolean\"\n       },\n       \"canStartApproval\": {\n        \"description\": \"Whether the current user can start an approval on the file.\",\n        \"type\": \"boolean\"\n       },\n       \"canDisableInheritedPermissions\": {\n        \"description\": \"Whether a user can disable inherited permissions.\",\n        \"type\": \"boolean\"\n       },\n       \"canCopy\": {\n        \"description\": \"Output only. Whether the current user can copy this file. For an item in a shared drive, whether the current user can copy non-folder descendants of this item, or this item if it's not a folder.\",\n        \"type\": \"boolean\"\n       },\n       \"canAddFolderFromAnotherDrive\": {\n        \"description\": \"Output only. Whether the current user can add a folder from another drive (different shared drive or My Drive) to this folder. This is `false` when the item isn't a folder. Only populated for items in shared drives.\",\n        \"type\": \"boolean\"\n       },\n       \"canAddMyDriveParent\": {\n        \"description\": \"Output only. Whether the current user can add a parent for the item without removing an existing parent in the same request. Not populated for shared drive files.\",\n        \"type\": \"boolean\"\n       },\n       \"canAddChildren\": {\n        \"description\": \"Output only. Whether the current user can add children to this folder. This is always `false` when the item isn't a folder.\",\n        \"type\": \"boolean\"\n       },\n       \"canMoveItemWithinTeamDrive\": {\n        \"description\": \"Deprecated: Output only. Use `canMoveItemWithinDrive` instead.\",\n        \"type\": \"boolean\"\n       }\n      }\n     },\n     \"teamDriveId\": {\n      \"description\": \"Deprecated: Output only. Use `driveId` instead.\",\n      \"type\": \"string\"\n     },\n     \"folderColorRgb\": {\n      \"description\": \"The color for a folder or a shortcut to a folder as an RGB hex string. The supported colors are published in the `folderColorPalette` field of the [`about`](/workspace/drive/api/reference/rest/v3/about) resource. If an unsupported color is specified, the closest color in the palette is used instead.\",\n      \"type\": \"string\"\n     },\n     \"thumbnailVersion\": {\n      \"description\": \"Output only. The thumbnail version for use in thumbnail cache invalidation.\",\n      \"type\": \"string\",\n      \"format\": \"int64\"\n     },\n     \"fullFileExtension\": {\n      \"description\": \"Output only. The full file extension extracted from the `name` field. May contain multiple concatenated extensions, such as \\\"tar.gz\\\". This is only available for files with binary content in Google Drive. This is automatically updated when the `name` field changes, however it's not cleared if the new name doesn't contain a valid extension.\",\n      \"type\": \"string\"\n     },\n     \"headRevisionId\": {\n      \"description\": \"Output only. The ID of the file's head revision. This is currently only available for files with binary content in Google Drive.\",\n      \"type\": \"string\"\n     },\n     \"id\": {\n      \"description\": \"The ID of the file.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"ContentRestriction\": {\n    \"description\": \"A restriction for accessing the content of the file.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"type\": {\n      \"description\": \"Output only. The type of the content restriction. Currently the only possible value is `globalContentRestriction`.\",\n      \"type\": \"string\"\n     },\n     \"reason\": {\n      \"description\": \"Reason for why the content of the file is restricted. This is only mutable on requests that also set `readOnly=true`.\",\n      \"type\": \"string\"\n     },\n     \"systemRestricted\": {\n      \"description\": \"Output only. Whether the content restriction was applied by the system, for example due to an esignature. Users cannot modify or remove system restricted content restrictions.\",\n      \"type\": \"boolean\"\n     },\n     \"readOnly\": {\n      \"description\": \"Whether the content of the file is read-only. If a file is read-only, a new revision of the file may not be added, comments may not be added or modified, and the title of the file may not be modified.\",\n      \"type\": \"boolean\"\n     },\n     \"restrictingUser\": {\n      \"$ref\": \"#/components/schemas/User\"\n     },\n     \"ownerRestricted\": {\n      \"description\": \"Whether the content restriction can only be modified or removed by a user who owns the file. For files in shared drives, any user with `organizer` capabilities can modify or remove this content restriction.\",\n      \"type\": \"boolean\"\n     },\n     \"restrictionTime\": {\n      \"description\": \"The time at which the content restriction was set (formatted RFC 3339 timestamp). Only populated if readOnly is true.\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     }\n    }\n   },\n   \"DriveList\": {\n    \"description\": \"A list of shared drives.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"drives\": {\n      \"description\": \"The list of shared drives. If nextPageToken is populated, then this list may be incomplete and an additional page of results should be fetched.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Drive\"\n      }\n     },\n     \"nextPageToken\": {\n      \"description\": \"The page token for the next page of shared drives. This will be absent if the end of the list has been reached. If the token is rejected for any reason, it should be discarded, and pagination should be restarted from the first page of results. The page token is typically valid for several hours. However, if new items are added or removed, your expected results might differ.\",\n      \"type\": \"string\"\n     },\n     \"kind\": {\n      \"description\": \"Identifies what kind of resource this is. Value: the fixed string `\\\"drive#driveList\\\"`.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"App\": {\n    \"description\": \"The `apps` resource provides a list of apps that a user has installed, with information about each app's supported MIME types, file extensions, and other details. Some resource methods (such as `apps.get`) require an `appId`. Use the `apps.list` method to retrieve the ID for an installed application.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"primaryFileExtensions\": {\n      \"description\": \"The list of primary file extensions.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"icons\": {\n      \"description\": \"The various icons for the app.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/AppIcons\"\n      }\n     },\n     \"createUrl\": {\n      \"description\": \"The URL to create a file with this app.\",\n      \"type\": \"string\"\n     },\n     \"name\": {\n      \"description\": \"The name of the app.\",\n      \"type\": \"string\"\n     },\n     \"supportsOfflineCreate\": {\n      \"description\": \"Whether this app supports creating files when offline.\",\n      \"type\": \"boolean\"\n     },\n     \"supportsCreate\": {\n      \"description\": \"Whether this app supports creating objects.\",\n      \"type\": \"boolean\"\n     },\n     \"productUrl\": {\n      \"description\": \"A link to the product listing for this app.\",\n      \"type\": \"string\"\n     },\n     \"secondaryFileExtensions\": {\n      \"description\": \"The list of secondary file extensions.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"longDescription\": {\n      \"description\": \"A long description of the app.\",\n      \"type\": \"string\"\n     },\n     \"id\": {\n      \"description\": \"The ID of the app.\",\n      \"type\": \"string\"\n     },\n     \"createInFolderTemplate\": {\n      \"description\": \"The template URL to create a file with this app in a given folder. The template contains the {folderId} to be replaced by the folder ID house the new file.\",\n      \"type\": \"string\"\n     },\n     \"hasDriveWideScope\": {\n      \"description\": \"Whether the app has Drive-wide scope. An app with Drive-wide scope can access all files in the user's Drive.\",\n      \"type\": \"boolean\"\n     },\n     \"openUrlTemplate\": {\n      \"description\": \"The template URL for opening files with this app. The template contains {ids} or {exportIds} to be replaced by the actual file IDs. For more information, see Open Files for the full documentation.\",\n      \"type\": \"string\"\n     },\n     \"shortDescription\": {\n      \"description\": \"A short description of the app.\",\n      \"type\": \"string\"\n     },\n     \"supportsImport\": {\n      \"description\": \"Whether this app supports importing from Google Docs.\",\n      \"type\": \"boolean\"\n     },\n     \"secondaryMimeTypes\": {\n      \"description\": \"The list of secondary MIME types.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"useByDefault\": {\n      \"description\": \"Whether the app is selected as the default handler for the types it supports.\",\n      \"type\": \"boolean\"\n     },\n     \"kind\": {\n      \"description\": \"Output only. Identifies what kind of resource this is. Value: the fixed string \\\"drive#app\\\".\",\n      \"type\": \"string\"\n     },\n     \"primaryMimeTypes\": {\n      \"description\": \"The list of primary MIME types.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     },\n     \"productId\": {\n      \"description\": \"The ID of the product listing for this app.\",\n      \"type\": \"string\"\n     },\n     \"objectType\": {\n      \"description\": \"The type of object this app creates such as a Chart. If empty, the app name should be used instead.\",\n      \"type\": \"string\"\n     },\n     \"supportsMultiOpen\": {\n      \"description\": \"Whether this app supports opening more than one file.\",\n      \"type\": \"boolean\"\n     },\n     \"installed\": {\n      \"description\": \"Whether the app is installed.\",\n      \"type\": \"boolean\"\n     },\n     \"authorized\": {\n      \"description\": \"Whether the app is authorized to access data on the user's Drive.\",\n      \"type\": \"boolean\"\n     }\n    }\n   },\n   \"CancelApprovalRequest\": {\n    \"description\": \"Request for cancelling an approval as an initiator.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"message\": {\n      \"description\": \"Optional. A message to accompany the cancellation of the approval. This message is included in notifications for the action and in the approval activity log.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"DecryptionMetadata\": {\n    \"description\": \"Representation of the CSE DecryptionMetadata.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"aes256GcmChunkSize\": {\n      \"description\": \"Chunk size used if content was encrypted with the AES 256 GCM Cipher. Possible values are: - default - small \",\n      \"type\": \"string\"\n     },\n     \"kaclsName\": {\n      \"description\": \"The name of the KACLS (Key ACL Service) used to encrypt the file.\",\n      \"type\": \"string\"\n     },\n     \"kaclsId\": {\n      \"description\": \"The ID of the KACLS (Key ACL Service) used to encrypt the file.\",\n      \"type\": \"string\",\n      \"format\": \"int64\"\n     },\n     \"keyFormat\": {\n      \"description\": \"Key format for the unwrapped key. Must be `tinkAesGcmKey`.\",\n      \"type\": \"string\"\n     },\n     \"wrappedKey\": {\n      \"description\": \"The URL-safe Base64 encoded wrapped key used to encrypt the contents of the file.\",\n      \"type\": \"string\"\n     },\n     \"encryptionResourceKeyHash\": {\n      \"description\": \"The URL-safe Base64 encoded HMAC-SHA256 digest of the resource metadata with its DEK (Data Encryption Key); see https://developers.google.com/workspace/cse/reference\",\n      \"type\": \"string\"\n     },\n     \"jwt\": {\n      \"description\": \"The signed JSON Web Token (JWT) which can be used to authorize the requesting user with the Key ACL Service (KACLS). The JWT asserts that the requesting user has at least read permissions on the file.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"Permission\": {\n    \"description\": \"A permission for a file. A permission grants a user, group, domain, or the world access to a file or a folder hierarchy. For more information, see [Share files, folders, and drives](https://developers.google.com/workspace/drive/api/guides/manage-sharing). By default, permission requests only return a subset of fields. Permission `kind`, `ID`, `type`, and `role` are always returned. To retrieve specific fields, see [Return specific fields](https://developers.google.com/workspace/drive/api/guides/fields-parameter). Some resource methods (such as `permissions.update`) require a `permissionId`. Use the `permissions.list` method to retrieve the ID for a file, folder, or shared drive.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"type\": {\n      \"description\": \"The type of the grantee. Supported values include: * `user` * `group` * `domain` * `anyone` When creating a permission, if `type` is `user` or `group`, you must provide an `emailAddress` for the user or group. If `type` is `domain`, you must provide a `domain`. If `type` is `anyone`, no extra information is required.\",\n      \"type\": \"string\"\n     },\n     \"domain\": {\n      \"description\": \"Output only. The domain to which this permission refers.\",\n      \"type\": \"string\"\n     },\n     \"deleted\": {\n      \"description\": \"Output only. Whether the account associated with this permission has been deleted. This field only pertains to permissions of type `user` or `group`.\",\n      \"type\": \"boolean\"\n     },\n     \"emailAddress\": {\n      \"description\": \"Output only. The email address of the user or group to which this permission refers.\",\n      \"type\": \"string\"\n     },\n     \"kind\": {\n      \"description\": \"Output only. Identifies what kind of resource this is. Value: the fixed string `\\\"drive#permission\\\"`.\",\n      \"type\": \"string\"\n     },\n     \"expirationTime\": {\n      \"description\": \"The time at which this permission will expire (RFC 3339 date-time). Expiration times have the following restrictions: - They can only be set on user and group permissions - The time must be in the future - The time cannot be more than a year in the future\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     },\n     \"teamDrivePermissionDetails\": {\n      \"description\": \"Output only. Deprecated: Output only. Use `permissionDetails` instead.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"object\",\n       \"properties\": {\n        \"teamDrivePermissionType\": {\n         \"description\": \"Deprecated: Output only. Use `permissionDetails/permissionType` instead.\",\n         \"type\": \"string\"\n        },\n        \"inherited\": {\n         \"description\": \"Deprecated: Output only. Use `permissionDetails/inherited` instead.\",\n         \"type\": \"boolean\"\n        },\n        \"inheritedFrom\": {\n         \"description\": \"Deprecated: Output only. Use `permissionDetails/inheritedFrom` instead.\",\n         \"type\": \"string\"\n        },\n        \"role\": {\n         \"description\": \"Deprecated: Output only. Use `permissionDetails/role` instead.\",\n         \"type\": \"string\"\n        }\n       }\n      }\n     },\n     \"id\": {\n      \"description\": \"Output only. The ID of this permission. This is a unique identifier for the grantee, and is published in the [User resource](https://developers.google.com/workspace/drive/api/reference/rest/v3/User) as `permissionId`. IDs should be treated as opaque values.\",\n      \"type\": \"string\"\n     },\n     \"pendingOwner\": {\n      \"description\": \"Whether the account associated with this permission is a pending owner. Only populated for permissions of type `user` for files that aren't in a shared drive.\",\n      \"type\": \"boolean\"\n     },\n     \"allowFileDiscovery\": {\n      \"description\": \"Whether the permission allows the file to be discovered through search. This is only applicable for permissions of type `domain` or `anyone`.\",\n      \"type\": \"boolean\"\n     },\n     \"inheritedPermissionsDisabled\": {\n      \"description\": \"When `true`, only organizers, owners, and users with permissions added directly on the item can access it.\",\n      \"type\": \"boolean\"\n     },\n     \"permissionDetails\": {\n      \"description\": \"Output only. Details of whether the permissions on this item are inherited or are directly on this item.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"object\",\n       \"properties\": {\n        \"role\": {\n         \"description\": \"Output only. The primary role for this user. Supported values include: * `owner` * `organizer` * `fileOrganizer` * `writer` * `commenter` * `reader` For more information, see [Roles and permissions](https://developers.google.com/workspace/drive/api/guides/ref-roles).\",\n         \"type\": \"string\"\n        },\n        \"inheritedFrom\": {\n         \"description\": \"Output only. The ID of the item from which this permission is inherited. This is only populated for items in shared drives.\",\n         \"type\": \"string\"\n        },\n        \"inherited\": {\n         \"description\": \"Output only. Whether this permission is inherited. This field is always populated. This is an output-only field.\",\n         \"type\": \"boolean\"\n        },\n        \"permissionType\": {\n         \"description\": \"Output only. The permission type for this user. Supported values include: * `file` * `member`\",\n         \"type\": \"string\"\n        }\n       }\n      }\n     },\n     \"displayName\": {\n      \"description\": \"Output only. The \\\"pretty\\\" name of the value of the permission. The following is a list of examples for each type of permission: * `user` - User's full name, as defined for their Google Account, such as \\\"Dana A.\\\" * `group` - Name of the Google Group, such as \\\"The Company Administrators.\\\" * `domain` - String domain name, such as \\\"cymbalgroup.com.\\\" * `anyone` - No `displayName` is present.\",\n      \"type\": \"string\"\n     },\n     \"role\": {\n      \"description\": \"The role granted by this permission. Supported values include: * `owner` * `organizer` * `fileOrganizer` * `writer` * `commenter` * `reader` For more information, see [Roles and permissions](https://developers.google.com/workspace/drive/api/guides/ref-roles).\",\n      \"type\": \"string\"\n     },\n     \"photoLink\": {\n      \"description\": \"Output only. A link to the user's profile photo, if available.\",\n      \"type\": \"string\"\n     },\n     \"view\": {\n      \"description\": \"Indicates the view for this permission. Only populated for permissions that belong to a view. The only supported values are `published` and `metadata`: * `published`: The permission's role is `publishedReader`. * `metadata`: The item is only visible to the `metadata` view because the item has limited access and the scope has at least read access to the parent. The `metadata` view is only supported on folders. For more information, see [Views](https://developers.google.com/workspace/drive/api/guides/ref-roles#views).\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"AddReviewer\": {\n    \"description\": \"Representation of a reviewer addition.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"addedReviewerEmail\": {\n      \"description\": \"Required. The email of the reviewer to add.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"AccessProposalRoleAndView\": {\n    \"description\": \"A wrapper for the role and view of an access proposal. For more information, see [Roles and permissions](https://developers.google.com/workspace/drive/api/guides/ref-roles).\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"role\": {\n      \"description\": \"The role that was proposed by the requester. The supported values are: * `writer` * `commenter` * `reader`\",\n      \"type\": \"string\"\n     },\n     \"view\": {\n      \"description\": \"Indicates the view for this access proposal. Only populated for proposals that belong to a view. Only `published` is supported.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"ApprovalList\": {\n    \"description\": \"The response of an approvals list request.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"kind\": {\n      \"description\": \"This is always drive#approvalList\",\n      \"type\": \"string\"\n     },\n     \"items\": {\n      \"description\": \"The list of approvals. If `nextPageToken` is populated, then this list may be incomplete and an additional page of results should be fetched.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Approval\"\n      }\n     },\n     \"nextPageToken\": {\n      \"description\": \"The page token for the next page of approvals. This is absent if the end of the approvals list has been reached. If the token is rejected for any reason, it should be discarded, and pagination should be restarted from the first page of results.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"Approval\": {\n    \"description\": \"Metadata for an approval. An approval is a review or approve process for a Drive item.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"createTime\": {\n      \"description\": \"Output only. The time the approval was created.\",\n      \"type\": \"string\",\n      \"format\": \"google-datetime\"\n     },\n     \"modifyTime\": {\n      \"description\": \"Output only. The most recent time the approval was modified.\",\n      \"type\": \"string\",\n      \"format\": \"google-datetime\"\n     },\n     \"initiator\": {\n      \"$ref\": \"#/components/schemas/User\"\n     },\n     \"status\": {\n      \"description\": \"Output only. The status of the approval at the time this resource was requested.\",\n      \"type\": \"string\",\n      \"enum\": [\n       \"STATUS_UNSPECIFIED\",\n       \"IN_PROGRESS\",\n       \"APPROVED\",\n       \"CANCELLED\",\n       \"DECLINED\"\n      ]\n     },\n     \"completeTime\": {\n      \"description\": \"Output only. The time the approval was completed.\",\n      \"type\": \"string\",\n      \"format\": \"google-datetime\"\n     },\n     \"kind\": {\n      \"description\": \"This is always drive#approval.\",\n      \"type\": \"string\"\n     },\n     \"dueTime\": {\n      \"description\": \"The time that the approval is due.\",\n      \"type\": \"string\",\n      \"format\": \"google-datetime\"\n     },\n     \"reviewerResponses\": {\n      \"description\": \"The responses made on the approval by reviewers.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/ReviewerResponse\"\n      }\n     },\n     \"targetFileId\": {\n      \"description\": \"Target file id of the approval.\",\n      \"type\": \"string\"\n     },\n     \"approvalId\": {\n      \"description\": \"The approval ID.\",\n      \"type\": \"string\"\n     },\n     \"fileContentChangeBehavior\": {\n      \"description\": \"Output only. The behavior of the approval when the file content changes.\",\n      \"type\": \"string\",\n      \"enum\": [\n       \"FILE_CONTENT_CHANGE_BEHAVIOR_UNSPECIFIED\",\n       \"RESET_APPROVAL\",\n       \"NO_APPROVAL_ACTION\"\n      ]\n     }\n    }\n   },\n   \"CommentApprovalRequest\": {\n    \"description\": \"Request for commenting on an approval.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"message\": {\n      \"description\": \"Required. A message to comment on the approval. This message is included in notifications for the action and in the approval activity log.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"TeamDrive\": {\n    \"description\": \"Deprecated: use the drive collection instead. Next ID: 33\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"restrictions\": {\n      \"description\": \"A set of restrictions that apply to this Team Drive or items inside this Team Drive.\",\n      \"type\": \"object\",\n      \"properties\": {\n       \"teamMembersOnly\": {\n        \"description\": \"Whether access to items inside this Team Drive is restricted to members of this Team Drive.\",\n        \"type\": \"boolean\"\n       },\n       \"adminManagedRestrictions\": {\n        \"description\": \"Whether administrative privileges on this Team Drive are required to modify restrictions.\",\n        \"type\": \"boolean\"\n       },\n       \"sharingFoldersRequiresOrganizerPermission\": {\n        \"description\": \"If true, only users with the organizer role can share folders. If false, users with either the organizer role or the file organizer role can share folders.\",\n        \"type\": \"boolean\"\n       },\n       \"copyRequiresWriterPermission\": {\n        \"description\": \"Whether the options to copy, print, or download files inside this Team Drive, should be disabled for readers and commenters. When this restriction is set to `true`, it will override the similarly named field to `true` for any file inside this Team Drive.\",\n        \"type\": \"boolean\"\n       },\n       \"downloadRestriction\": {\n        \"$ref\": \"#/components/schemas/DownloadRestriction\"\n       },\n       \"domainUsersOnly\": {\n        \"description\": \"Whether access to this Team Drive and items inside this Team Drive is restricted to users of the domain to which this Team Drive belongs. This restriction may be overridden by other sharing policies controlled outside of this Team Drive.\",\n        \"type\": \"boolean\"\n       }\n      }\n     },\n     \"createdTime\": {\n      \"description\": \"The time at which the Team Drive was created (RFC 3339 date-time).\",\n      \"type\": \"string\",\n      \"format\": \"date-time\"\n     },\n     \"id\": {\n      \"description\": \"The ID of this Team Drive which is also the ID of the top level folder of this Team Drive.\",\n      \"type\": \"string\"\n     },\n     \"name\": {\n      \"description\": \"The name of this Team Drive.\",\n      \"type\": \"string\"\n     },\n     \"themeId\": {\n      \"description\": \"The ID of the theme from which the background image and color will be set. The set of possible `teamDriveThemes` can be retrieved from a `drive.about.get` response. When not specified on a `drive.teamdrives.create` request, a random theme is chosen from which the background image and color are set. This is a write-only field; it can only be set on requests that don't set `colorRgb` or `backgroundImageFile`.\",\n      \"type\": \"string\"\n     },\n     \"colorRgb\": {\n      \"description\": \"The color of this Team Drive as an RGB hex string. It can only be set on a `drive.teamdrives.update` request that does not set `themeId`.\",\n      \"type\": \"string\"\n     },\n     \"backgroundImageLink\": {\n      \"description\": \"A short-lived link to this Team Drive's background image.\",\n      \"type\": \"string\"\n     },\n     \"backgroundImageFile\": {\n      \"description\": \"The background image file for a Team Drive.\",\n      \"type\": \"object\",\n      \"properties\": {\n       \"id\": {\n        \"description\": \"The ID of an image file in Drive to use for the background image.\",\n        \"type\": \"string\"\n       },\n       \"xCoordinate\": {\n        \"description\": \"The X coordinate of the upper left corner of the cropping area in the background image. This is a value in the closed range of 0 to 1. This value represents the horizontal distance from the left side of the entire image to the left side of the cropping area divided by the width of the entire image.\",\n        \"type\": \"number\",\n        \"format\": \"float\"\n       },\n       \"width\": {\n        \"description\": \"The width of the cropped image in the closed range of 0 to 1. This value represents the width of the cropped image divided by the width of the entire image. The height is computed by applying a width to height aspect ratio of 80 to 9. The resulting image must be at least 1280 pixels wide and 144 pixels high.\",\n        \"type\": \"number\",\n        \"format\": \"float\"\n       },\n       \"yCoordinate\": {\n        \"description\": \"The Y coordinate of the upper left corner of the cropping area in the background image. This is a value in the closed range of 0 to 1. This value represents the vertical distance from the top side of the entire image to the top side of the cropping area divided by the height of the entire image.\",\n        \"type\": \"number\",\n        \"format\": \"float\"\n       }\n      }\n     },\n     \"capabilities\": {\n      \"description\": \"Capabilities the current user has on this Team Drive.\",\n      \"type\": \"object\",\n      \"properties\": {\n       \"canDeleteTeamDrive\": {\n        \"description\": \"Whether the current user can delete this Team Drive. Attempting to delete the Team Drive may still fail if there are untrashed items inside the Team Drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canComment\": {\n        \"description\": \"Whether the current user can comment on files in this Team Drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canRename\": {\n        \"description\": \"Whether the current user can rename files or folders in this Team Drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canChangeDownloadRestriction\": {\n        \"description\": \"Output only. Whether the current user can change organizer-applied download restrictions of this shared drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canEdit\": {\n        \"description\": \"Whether the current user can edit files in this Team Drive\",\n        \"type\": \"boolean\"\n       },\n       \"canChangeDomainUsersOnlyRestriction\": {\n        \"description\": \"Whether the current user can change the `domainUsersOnly` restriction of this Team Drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canTrashChildren\": {\n        \"description\": \"Whether the current user can trash children from folders in this Team Drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canReadRevisions\": {\n        \"description\": \"Whether the current user can read the revisions resource of files in this Team Drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canRenameTeamDrive\": {\n        \"description\": \"Whether the current user can rename this Team Drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canRemoveChildren\": {\n        \"description\": \"Deprecated: Use `canDeleteChildren` or `canTrashChildren` instead.\",\n        \"type\": \"boolean\"\n       },\n       \"canChangeTeamDriveBackground\": {\n        \"description\": \"Whether the current user can change the background of this Team Drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canChangeTeamMembersOnlyRestriction\": {\n        \"description\": \"Whether the current user can change the `teamMembersOnly` restriction of this Team Drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canDeleteChildren\": {\n        \"description\": \"Whether the current user can delete children from folders in this Team Drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canCopy\": {\n        \"description\": \"Whether the current user can copy files in this Team Drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canManageMembers\": {\n        \"description\": \"Whether the current user can add members to this Team Drive or remove them or change their role.\",\n        \"type\": \"boolean\"\n       },\n       \"canListChildren\": {\n        \"description\": \"Whether the current user can list the children of folders in this Team Drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canResetTeamDriveRestrictions\": {\n        \"description\": \"Whether the current user can reset the Team Drive restrictions to defaults.\",\n        \"type\": \"boolean\"\n       },\n       \"canAddChildren\": {\n        \"description\": \"Whether the current user can add children to folders in this Team Drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canDownload\": {\n        \"description\": \"Whether the current user can download files in this Team Drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canChangeSharingFoldersRequiresOrganizerPermissionRestriction\": {\n        \"description\": \"Whether the current user can change the `sharingFoldersRequiresOrganizerPermission` restriction of this Team Drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canShare\": {\n        \"description\": \"Whether the current user can share files or folders in this Team Drive.\",\n        \"type\": \"boolean\"\n       },\n       \"canChangeCopyRequiresWriterPermissionRestriction\": {\n        \"description\": \"Whether the current user can change the `copyRequiresWriterPermission` restriction of this Team Drive.\",\n        \"type\": \"boolean\"\n       }\n      }\n     },\n     \"orgUnitId\": {\n      \"description\": \"The organizational unit of this shared drive. This field is only populated on `drives.list` responses when the `useDomainAdminAccess` parameter is set to `true`.\",\n      \"type\": \"string\"\n     },\n     \"kind\": {\n      \"description\": \"Identifies what kind of resource this is. Value: the fixed string `\\\"drive#teamDrive\\\"`.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"ReassignApprovalRequest\": {\n    \"description\": \"Request for reassigning an approval. Reviewers can be added or replaced, but not removed.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"addReviewers\": {\n      \"description\": \"Optional. The list of reviewers to add.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/AddReviewer\"\n      }\n     },\n     \"message\": {\n      \"description\": \"Optional. A message to send to the new reviewers. This message is included in notifications for the action and in the approval activity log.\",\n      \"type\": \"string\"\n     },\n     \"replaceReviewers\": {\n      \"description\": \"Optional. The list of reviewer replacements.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/ReplaceReviewer\"\n      }\n     }\n    }\n   }\n  },\n  \"securitySchemes\": {\n   \"bearer\": {\n    \"type\": \"http\",\n    \"scheme\": \"bearer\"\n   }\n  }\n }\n}\n"},{"path":"products/drive/openapi.ts","content":"// Generated by scripts/google-vendor.ts from packages/google-drive; edit the original and rerun it.\n// drive-openapi.json is generated from Google's own Drive v3 Discovery document (revision 20261005)\n// by discovery-to-openapi.mjs; see README. Credentials go only to www.googleapis.com.\nimport type { JsonObject } from \"apps\";\nimport type { OpenapiToolNamesOptions } from \"apps/openapi\";\nimport drive from \"./drive-openapi.json\" with { type: \"json\" };\n\n// The inferred JSON type has no index signature, so widen it once here.\nconst document: JsonObject = JSON.parse(JSON.stringify(drive));\n\n// Every operation in the generated document already carries a plain bearer requirement.\nexport const options = {\n  source: { document },\n  allowedOrigin: \"https://www.googleapis.com\",\n  securitySchemes: { bearer: { type: \"http\", scheme: \"bearer\" } },\n  methods: {\n    oauth: [{ scheme: \"bearer\", field: \"access_token\", part: \"value\", prefix: \"\" }],\n  },\n  oauth: [],\n} satisfies OpenapiToolNamesOptions;\n"},{"path":"products/forms/openapi.ts","content":"// Generated by scripts/google-vendor.ts from packages/google-forms; edit the original and rerun it.\nimport type { OpenapiToolNamesOptions } from \"apps/openapi\";\n\n// APIs.guru's conversion of Google's official Forms v1 Discovery document. The conversion makes\n// every operation require its \"Oauth2\" and \"Oauth2c\" schemes together; both mean the same bearer\n// access token, so both are declared as bearer and filled from the oauth method's access token.\nexport const options = {\n  source: { url: \"https://api.apis.guru/v2/specs/googleapis.com/forms/v1/openapi.json\" },\n  allowedOrigin: \"https://forms.googleapis.com\",\n  securitySchemes: {\n    Oauth2: { type: \"http\", scheme: \"bearer\" },\n    Oauth2c: { type: \"http\", scheme: \"bearer\" },\n  },\n  methods: {\n    oauth: [\n      { scheme: \"Oauth2\", field: \"access_token\", part: \"value\", prefix: \"\" },\n      { scheme: \"Oauth2c\", field: \"access_token\", part: \"value\", prefix: \"\" },\n    ],\n  },\n  oauth: [],\n} satisfies OpenapiToolNamesOptions;\n"},{"path":"products/gmail/openapi.ts","content":"// Generated by scripts/google-vendor.ts from packages/gmail; edit the original and rerun it.\nimport type { OpenapiToolNamesOptions } from \"apps/openapi\";\n\n// Google publishes the Gmail API as a Discovery document, not OpenAPI. This is APIs.guru's\n// maintained OpenAPI conversion of that document (unofficial). Its oauth2 schemes are\n// implicit-flow descriptions, so bearer schemes of the same names carry the access token instead.\nexport const options = {\n  source: { url: \"https://api.apis.guru/v2/specs/googleapis.com/gmail/v1/openapi.json\" },\n  allowedOrigin: \"https://gmail.googleapis.com\",\n  securitySchemes: {\n    Oauth2c: { type: \"http\", scheme: \"bearer\" },\n    Oauth2: { type: \"http\", scheme: \"bearer\" },\n  },\n  methods: {\n    oauth: [\n      { scheme: \"Oauth2c\", field: \"access_token\", part: \"value\", prefix: \"\" },\n      { scheme: \"Oauth2\", field: \"access_token\", part: \"value\", prefix: \"\" },\n    ],\n  },\n  oauth: [],\n} satisfies OpenapiToolNamesOptions;\n"},{"path":"products/meet/tools.ts","content":"// Generated by scripts/google-vendor.ts from packages/google-meet; edit the original and rerun it.\n// The tools, without the account: index.ts and packages/google (through scripts/google-vendor.ts) both mount them.\nimport {\n  array,\n  decodeJson,\n  json,\n  mutation,\n  number,\n  object,\n  query,\n  router,\n  string,\n} from \"apps\";\n\nconst base = \"https://meet.googleapis.com/v2\";\n\n/** The router's metadata, shared with packages/google. */\nexport const meta = {\n  title: \"Google Meet\",\n  description: \"Create and configure Google Meet spaces, and read meeting records, participants, recordings and transcripts.\",\n};\n\ntype Fetch = typeof fetch;\ntype Search = Record<string, string | number | undefined>;\n\nconst spaceName = string({ minLength: 1 });\nconst pageOnly = { pageSize: number().optional(), pageToken: string().optional() };\nconst paging = { ...pageOnly, filter: string().optional() };\n\nexport function tools(token: string, fetcher: Fetch, signal: AbortSignal | undefined) {\n  const call = async (path: string, init: { method?: string; body?: unknown; search?: Search } = {}) => {\n    const url = new URL(`${base}/${path}`);\n    for (const [key, value] of Object.entries(init.search ?? {})) if (value !== undefined) url.searchParams.set(key, String(value));\n    const response = await fetcher(url.toString(), {\n      method: init.method ?? \"GET\",\n      signal,\n      headers: { Authorization: `Bearer ${token}`, \"content-type\": \"application/json\" },\n      body: init.body === undefined ? undefined : JSON.stringify(init.body),\n    });\n    return decodeJson(response, json());\n  };\n  // Resource names such as \"spaces/abc123\" are path segments, not single values: keep the slashes.\n  const path = (name: string) => name.split(\"/\").map(encodeURIComponent).join(\"/\");\n  const list = (parent: string, collection: string, input: { pageSize?: number; pageToken?: string; filter?: string }) =>\n    call(`${path(parent)}/${collection}`, { search: input });\n\n  return router({\n    spaces: router(\n      {\n        create: mutation(\n          {\n            description:\n              \"Create a meeting space. Optionally pass a config object (accessType OPEN | TRUSTED | RESTRICTED, entryPointAccess, moderation, attendanceReportGenerationType, artifactConfig). Returns the space including meetingUri and meetingCode.\",\n            input: object({ config: json().optional() }),\n          },\n          async (_ctx, { config }) => call(\"spaces\", { method: \"POST\", body: config === undefined ? {} : { config } }),\n        ),\n        get: query(\n          {\n            description: \"Get a meeting space by resource name (spaces/{id}) or by meeting code (spaces/abc-mnop-xyz).\",\n            input: object({ name: spaceName }),\n          },\n          async (_ctx, { name }) => call(path(name)),\n        ),\n        update: mutation(\n          {\n            description:\n              \"Update a space's config. updateMask is a comma-separated field mask such as config.accessType or config.moderation.\",\n            input: object({ name: spaceName, config: json(), updateMask: string() }),\n          },\n          async (_ctx, { name, config, updateMask }) =>\n            call(path(name), { method: \"PATCH\", body: { config }, search: { updateMask } }),\n        ),\n        endActiveConference: mutation(\n          {\n            description: \"End the active conference in a space, removing all participants.\",\n            input: object({ name: spaceName }),\n          },\n          async (_ctx, { name }) => call(`${path(name)}:endActiveConference`, { method: \"POST\", body: {} }),\n        ),\n        members: router({\n          list: query(\n            { description: \"List members of a space (spaces/{id}).\", input: object({ parent: spaceName, ...pageOnly }) },\n            async (_ctx, { parent, ...rest }) => list(parent, \"members\", rest),\n          ),\n          get: query(\n            { description: \"Get a space member by name (spaces/{id}/members/{member}).\", input: object({ name: spaceName }) },\n            async (_ctx, { name }) => call(path(name)),\n          ),\n          create: mutation(\n            {\n              description:\n                \"Add a member to a space. member is a Member object, e.g. { user: \\\"users/{id}\\\", role: \\\"COHOST\\\" }.\",\n              input: object({ parent: spaceName, member: json() }),\n            },\n            async (_ctx, { parent, member }) => call(`${path(parent)}/members`, { method: \"POST\", body: member }),\n          ),\n          update: mutation(\n            {\n              description: \"Update a space member, for example their role. updateMask is a comma-separated field mask.\",\n              input: object({ name: spaceName, member: json(), updateMask: string().optional() }),\n            },\n            async (_ctx, { name, member, updateMask }) =>\n              call(path(name), { method: \"PATCH\", body: member, search: { updateMask } }),\n          ),\n          delete: mutation(\n            { description: \"Remove a member from a space.\", input: object({ name: spaceName }) },\n            async (_ctx, { name }) => call(path(name), { method: \"DELETE\" }),\n          ),\n          batchUpdate: mutation(\n            {\n              description: \"Update several space members at once. requests is an array of UpdateMemberRequest objects.\",\n              input: object({ parent: spaceName, requests: array(json()) }),\n            },\n            async (_ctx, { parent, requests }) =>\n              call(`${path(parent)}/members:batchUpdate`, { method: \"POST\", body: { requests: [...requests] } }),\n          ),\n        }),\n      },\n      { title: \"Spaces\", description: \"Create, read and configure meeting spaces and their members.\" },\n    ),\n    conferenceRecords: router(\n      {\n        list: query(\n          {\n            description:\n              \"List conference records (past and ongoing meetings you can access). filter supports space.meeting_code, space.name, start_time, end_time.\",\n            input: object(paging),\n          },\n          async (_ctx, input) => call(\"conferenceRecords\", { search: input }),\n        ),\n        get: query(\n          { description: \"Get a conference record (conferenceRecords/{id}).\", input: object({ name: spaceName }) },\n          async (_ctx, { name }) => call(path(name)),\n        ),\n        participants: router({\n          list: query(\n            {\n              description: \"List participants of a conference record (conferenceRecords/{id}).\",\n              input: object({ parent: spaceName, ...paging }),\n            },\n            async (_ctx, { parent, ...rest }) => list(parent, \"participants\", rest),\n          ),\n          get: query(\n            {\n              description: \"Get a participant (conferenceRecords/{id}/participants/{participant}).\",\n              input: object({ name: spaceName }),\n            },\n            async (_ctx, { name }) => call(path(name)),\n          ),\n          sessions: router({\n            list: query(\n              {\n                description: \"List a participant's join/leave sessions (conferenceRecords/{id}/participants/{participant}).\",\n                input: object({ parent: spaceName, ...paging }),\n              },\n              async (_ctx, { parent, ...rest }) => list(parent, \"participantSessions\", rest),\n            ),\n            get: query(\n              { description: \"Get a participant session by full resource name.\", input: object({ name: spaceName }) },\n              async (_ctx, { name }) => call(path(name)),\n            ),\n          }),\n        }),\n        recordings: router({\n          list: query(\n            {\n              description: \"List recordings of a conference record. Each has a Drive file reference.\",\n              input: object({ parent: spaceName, ...pageOnly }),\n            },\n            async (_ctx, { parent, ...rest }) => list(parent, \"recordings\", rest),\n          ),\n          get: query(\n            {\n              description: \"Get a recording (conferenceRecords/{id}/recordings/{recording}).\",\n              input: object({ name: spaceName }),\n            },\n            async (_ctx, { name }) => call(path(name)),\n          ),\n        }),\n        transcripts: router({\n          list: query(\n            {\n              description: \"List transcripts of a conference record. Each has a Google Docs reference.\",\n              input: object({ parent: spaceName, ...pageOnly }),\n            },\n            async (_ctx, { parent, ...rest }) => list(parent, \"transcripts\", rest),\n          ),\n          get: query(\n            {\n              description: \"Get a transcript (conferenceRecords/{id}/transcripts/{transcript}).\",\n              input: object({ name: spaceName }),\n            },\n            async (_ctx, { name }) => call(path(name)),\n          ),\n          entries: router({\n            list: query(\n              {\n                description: \"List the spoken entries of a transcript (conferenceRecords/{id}/transcripts/{transcript}).\",\n                input: object({ parent: spaceName, ...pageOnly }),\n              },\n              async (_ctx, { parent, ...rest }) => list(parent, \"entries\", rest),\n            ),\n            get: query(\n              { description: \"Get one transcript entry by full resource name.\", input: object({ name: spaceName }) },\n              async (_ctx, { name }) => call(path(name)),\n            ),\n          }),\n        }),\n        smartNotes: router({\n          list: query(\n            {\n              description: \"List Gemini smart notes of a conference record. Each has a Google Docs reference.\",\n              input: object({ parent: spaceName, ...pageOnly }),\n            },\n            async (_ctx, { parent, ...rest }) => list(parent, \"smartNotes\", rest),\n          ),\n          get: query(\n            {\n              description: \"Get a smart note (conferenceRecords/{id}/smartNotes/{note}).\",\n              input: object({ name: spaceName }),\n            },\n            async (_ctx, { name }) => call(path(name)),\n          ),\n        }),\n      },\n      { title: \"Conference records\", description: \"Past and ongoing meetings: participants, recordings, transcripts and notes.\" },\n    ),\n  });\n}\n"},{"path":"products/photos/openapi.json","content":"{\n \"openapi\": \"3.0.3\",\n \"info\": {\n  \"title\": \"Photos Library API\",\n  \"version\": \"v1 (discovery revision 20261008)\",\n  \"description\": \"Manage photos, videos, and albums created by your app in Google Photos \"\n },\n \"servers\": [\n  {\n   \"url\": \"https://photoslibrary.googleapis.com\"\n  }\n ],\n \"security\": [\n  {\n   \"bearer\": []\n  }\n ],\n \"paths\": {\n  \"/v1/albums\": {\n   \"get\": {\n    \"operationId\": \"photoslibrary.albums.list\",\n    \"description\": \"Lists all albums created by your app.\",\n    \"parameters\": [\n     {\n      \"name\": \"pageSize\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Maximum number of albums to return in the response. Fewer albums might be returned than the specified number. The default `pageSize` is 20, the maximum is 50.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"A continuation token to get the next page of the results. Adding this to the request returns the rows after the `pageToken`. The `pageToken` should be the value returned in the `nextPageToken` parameter in the response to the `listAlbums` request.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"excludeNonAppCreatedData\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"If set, the results exclude media items that were not created by this app. Defaults to false (all albums are returned). This field is ignored if the photoslibrary.readonly.appcreateddata scope is used.\",\n      \"schema\": {\n       \"type\": \"boolean\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/ListAlbumsResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   },\n   \"post\": {\n    \"operationId\": \"photoslibrary.albums.create\",\n    \"description\": \"Creates an album in a user's Google Photos library.\",\n    \"parameters\": [\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Album\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/CreateAlbumRequest\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/v1/albums/{albumsId}:batchRemoveMediaItems\": {\n   \"post\": {\n    \"operationId\": \"photoslibrary.albums.batchRemoveMediaItems\",\n    \"description\": \"Removes one or more app created media items from a specified app created album. The media items and the album must have been created by the developer via the API. Partial success is not supported. The entire request will fail and no action will be performed on the album if an invalid media item or album is specified.\",\n    \"parameters\": [\n     {\n      \"name\": \"albumsId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Identifier segment albumsId of the resource name.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/BatchRemoveMediaItemsFromAlbumResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/BatchRemoveMediaItemsFromAlbumRequest\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/v1/albums/{albumsId}\": {\n   \"get\": {\n    \"operationId\": \"photoslibrary.albums.get\",\n    \"description\": \"Returns the app created album based on the specified `albumId`. The `albumId` must be the ID of an album created by your app.\",\n    \"parameters\": [\n     {\n      \"name\": \"albumsId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Identifier segment albumsId of the resource name.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Album\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   },\n   \"patch\": {\n    \"operationId\": \"photoslibrary.albums.patch\",\n    \"description\": \"Update the app created album with the specified `id`. Only the `id`, `title` and `cover_photo_media_item_id` fields of the album are read. The album must have been created by the developer via the API.\",\n    \"parameters\": [\n     {\n      \"name\": \"updateMask\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Required. Indicate what fields in the provided album to update. The only valid values are `title` and `cover_photo_media_item_id`.\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"google-fieldmask\"\n      }\n     },\n     {\n      \"name\": \"albumsId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Identifier segment albumsId of the resource name.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Album\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/Album\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/v1/albums/{albumsId}:batchAddMediaItems\": {\n   \"post\": {\n    \"operationId\": \"photoslibrary.albums.batchAddMediaItems\",\n    \"description\": \"Adds one or more app created media items in a user's Google Photos library to an app created album. The media items and albums must have been created by the developer via the API. Media items are added to the end of the album. If multiple media items are given, they are added in the order specified in this call. Each album can contain up to 20,000 media items. Partial success is not supported. The entire request will fail if an invalid media item or album is specified.\",\n    \"parameters\": [\n     {\n      \"name\": \"albumsId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Identifier segment albumsId of the resource name.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/BatchAddMediaItemsToAlbumResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/BatchAddMediaItemsToAlbumRequest\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/v1/albums/{albumsId}:addEnrichment\": {\n   \"post\": {\n    \"operationId\": \"photoslibrary.albums.addEnrichment\",\n    \"description\": \"Adds an enrichment at a specified position in an app created created album.\",\n    \"parameters\": [\n     {\n      \"name\": \"albumsId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Identifier segment albumsId of the resource name.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/AddEnrichmentToAlbumResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/AddEnrichmentToAlbumRequest\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/v1/mediaItems/{mediaItemsId}\": {\n   \"get\": {\n    \"operationId\": \"photoslibrary.mediaItems.get\",\n    \"description\": \"Returns the app created media item for the specified media item identifier.\",\n    \"parameters\": [\n     {\n      \"name\": \"mediaItemsId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Identifier segment mediaItemsId of the resource name.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/MediaItem\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   },\n   \"patch\": {\n    \"operationId\": \"photoslibrary.mediaItems.patch\",\n    \"description\": \"Update the app created media item with the specified `id`. Only the `id` and `description` fields of the media item are read. The media item must have been created by the developer via the API.\",\n    \"parameters\": [\n     {\n      \"name\": \"updateMask\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Required. Indicate what fields in the provided media item to update. The only valid value is `description`.\",\n      \"schema\": {\n       \"type\": \"string\",\n       \"format\": \"google-fieldmask\"\n      }\n     },\n     {\n      \"name\": \"mediaItemsId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Identifier segment mediaItemsId of the resource name.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/MediaItem\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/MediaItem\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/v1/mediaItems:batchGet\": {\n   \"get\": {\n    \"operationId\": \"photoslibrary.mediaItems.batchGet\",\n    \"description\": \"Returns the list of app created media items for the specified media item identifiers. Items are returned in the same order as the supplied identifiers.\",\n    \"parameters\": [\n     {\n      \"name\": \"mediaItemIds\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Required. Identifiers of the media items to be requested. Must not contain repeated identifiers and cannot be empty. The maximum number of media items that can be retrieved in one call is 50.\",\n      \"schema\": {\n       \"type\": \"array\",\n       \"items\": {\n        \"type\": \"string\"\n       }\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/BatchGetMediaItemsResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/v1/mediaItems\": {\n   \"get\": {\n    \"operationId\": \"photoslibrary.mediaItems.list\",\n    \"description\": \"List all media items created by your app from a user's Google Photos library.\",\n    \"parameters\": [\n     {\n      \"name\": \"pageSize\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Maximum number of media items to return in the response. Fewer media items might be returned than the specified number. The default `pageSize` is 25, the maximum is 100.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"A continuation token to get the next page of the results. Adding this to the request returns the rows after the `pageToken`. The `pageToken` should be the value returned in the `nextPageToken` parameter in the response to the `listMediaItems` request.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/ListMediaItemsResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/v1/mediaItems:search\": {\n   \"post\": {\n    \"operationId\": \"photoslibrary.mediaItems.search\",\n    \"description\": \"Searches for app created media items in a user's Google Photos library. Only media items and ablums created by your app are returned. If no filters are set, then all app created media items in the user's library are returned. If an app created album is set, all media items in the specified album are returned. If filters are specified, app created media items that match the filters from the user's library are listed. If you set both the album and the filters, the request results in an error.\",\n    \"parameters\": [\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/SearchMediaItemsResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/SearchMediaItemsRequest\"\n       }\n      }\n     }\n    }\n   }\n  }\n },\n \"components\": {\n  \"schemas\": {\n   \"UnshareAlbumRequest\": {\n    \"description\": \"Request to unshare a shared album in Google Photos.\",\n    \"type\": \"object\",\n    \"properties\": {}\n   },\n   \"Photo\": {\n    \"description\": \"Metadata that is specific to a photo, such as, ISO, focal length and exposure time. Some of these fields may be null or not included.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"cameraModel\": {\n      \"description\": \"Model of the camera with which the photo was taken.\",\n      \"type\": \"string\"\n     },\n     \"exposureTime\": {\n      \"description\": \"Exposure time of the camera aperture when the photo was taken.\",\n      \"type\": \"string\",\n      \"format\": \"google-duration\"\n     },\n     \"focalLength\": {\n      \"description\": \"Focal length of the camera lens with which the photo was taken.\",\n      \"type\": \"number\",\n      \"format\": \"float\"\n     },\n     \"apertureFNumber\": {\n      \"description\": \"Aperture f number of the camera lens with which the photo was taken.\",\n      \"type\": \"number\",\n      \"format\": \"float\"\n     },\n     \"cameraMake\": {\n      \"description\": \"Brand of the camera with which the photo was taken.\",\n      \"type\": \"string\"\n     },\n     \"isoEquivalent\": {\n      \"description\": \"ISO of the camera with which the photo was taken.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     }\n    }\n   },\n   \"DateRange\": {\n    \"description\": \"Defines a range of dates. Both dates must be of the same format. For more information, see Date.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"endDate\": {\n      \"$ref\": \"#/components/schemas/Date\"\n     },\n     \"startDate\": {\n      \"$ref\": \"#/components/schemas/Date\"\n     }\n    }\n   },\n   \"SimpleMediaItem\": {\n    \"description\": \"A simple media item to be created in Google Photos via an upload token.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"fileName\": {\n      \"description\": \"File name with extension of the media item. This is shown to the user in Google Photos. The file name specified during the byte upload process is ignored if this field is set. The file name, including the file extension, shouldn't be more than 255 characters. This is an optional field.\",\n      \"type\": \"string\"\n     },\n     \"uploadToken\": {\n      \"description\": \"Token identifying the media bytes that have been uploaded to Google.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"NewEnrichmentItem\": {\n    \"description\": \"A new enrichment item to be added to an app created album, used by the `albums.addEnrichment` call.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"locationEnrichment\": {\n      \"$ref\": \"#/components/schemas/LocationEnrichment\"\n     },\n     \"mapEnrichment\": {\n      \"$ref\": \"#/components/schemas/MapEnrichment\"\n     },\n     \"textEnrichment\": {\n      \"$ref\": \"#/components/schemas/TextEnrichment\"\n     }\n    }\n   },\n   \"JoinSharedAlbumRequest\": {\n    \"description\": \"Request to join a shared album on behalf of the user. This uses a shareToken which can be acquired via the shareAlbum or listSharedAlbums calls.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"shareToken\": {\n      \"description\": \"Required. Token to join the shared album on behalf of the user.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"Album\": {\n    \"description\": \"Representation of an album in Google Photos. Albums are containers for media items. If an album has been shared by the application, it contains an extra `shareInfo` property.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"productUrl\": {\n      \"description\": \"[Output only] Google Photos URL for the album. The user needs to be signed in to their Google Photos account to access this link.\",\n      \"type\": \"string\"\n     },\n     \"title\": {\n      \"description\": \"Name of the album displayed to the user in their Google Photos account. This string shouldn't be more than 500 characters.\",\n      \"type\": \"string\"\n     },\n     \"id\": {\n      \"description\": \"Identifier for the album. This is a persistent identifier that can be used between sessions to identify this album.\",\n      \"type\": \"string\"\n     },\n     \"isWriteable\": {\n      \"description\": \"[Output only] True if you can create media items in this album. This field is based on the scopes granted and permissions of the album. If the scopes are changed or permissions of the album are changed, this field is updated.\",\n      \"type\": \"boolean\"\n     },\n     \"coverPhotoBaseUrl\": {\n      \"description\": \"[Output only] A URL to the cover photo's bytes. This shouldn't be used as is. Parameters should be appended to this URL before use. See the [developer documentation](https://developers.google.com/photos/library/guides/access-media-items#base-urls) for a complete list of supported parameters. For example, `'=w2048-h1024'` sets the dimensions of the cover photo to have a width of 2048 px and height of 1024 px.\",\n      \"type\": \"string\"\n     },\n     \"mediaItemsCount\": {\n      \"description\": \"[Output only] The number of media items in the album.\",\n      \"type\": \"string\",\n      \"format\": \"int64\"\n     },\n     \"coverPhotoMediaItemId\": {\n      \"description\": \"Identifier for the media item associated with the cover photo.\",\n      \"type\": \"string\"\n     },\n     \"shareInfo\": {\n      \"$ref\": \"#/components/schemas/ShareInfo\"\n     }\n    }\n   },\n   \"MediaTypeFilter\": {\n    \"description\": \"This filter defines the type of media items to be returned, for example, videos or photos. Only one media type is supported.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"mediaTypes\": {\n      \"description\": \"The types of media items to be included. This field should be populated with only one media type. If you specify multiple media types, it results in an error.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\",\n       \"enum\": [\n        \"ALL_MEDIA\",\n        \"VIDEO\",\n        \"PHOTO\"\n       ]\n      }\n     }\n    }\n   },\n   \"SearchMediaItemsResponse\": {\n    \"description\": \"List of media items that match the search parameters.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"mediaItems\": {\n      \"description\": \"Output only. List of media items that match the search parameters.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/MediaItem\"\n      }\n     },\n     \"nextPageToken\": {\n      \"description\": \"Output only. Use this token to get the next set of media items. Its presence is the only reliable indicator of more media items being available in the next request.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"TextEnrichment\": {\n    \"description\": \"An enrichment containing text.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"text\": {\n      \"description\": \"Text for this enrichment item.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"BatchCreateMediaItemsResponse\": {\n    \"description\": \"List of media items created.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"newMediaItemResults\": {\n      \"description\": \"Output only. List of media items created.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/NewMediaItemResult\"\n      }\n     }\n    }\n   },\n   \"CreateAlbumRequest\": {\n    \"description\": \"Request to create an album in Google Photos.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"album\": {\n      \"$ref\": \"#/components/schemas/Album\"\n     }\n    }\n   },\n   \"BatchGetMediaItemsResponse\": {\n    \"description\": \"Response to retrieve a list of app created media items.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"mediaItemResults\": {\n      \"description\": \"Output only. List of media items retrieved. Note that even if the call to BatchGetMediaItems succeeds, there may have been failures for some media items in the batch. These failures are indicated in each MediaItemResult.status.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/MediaItemResult\"\n      }\n     }\n    }\n   },\n   \"BatchRemoveMediaItemsFromAlbumRequest\": {\n    \"description\": \"Request to remove a list of media items from an album.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"mediaItemIds\": {\n      \"description\": \"Required. Identifiers of the MediaItems to be removed. Must not contain repeated identifiers and cannot be empty. The maximum number of media items that can be removed in one call is 50.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     }\n    }\n   },\n   \"Location\": {\n    \"description\": \"Represents a physical location.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"latlng\": {\n      \"$ref\": \"#/components/schemas/LatLng\"\n     },\n     \"locationName\": {\n      \"description\": \"Name of the location to be displayed.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"BatchCreateMediaItemsRequest\": {\n    \"description\": \"Request to create one or more media items in a user's Google Photos library. If an `albumid` from an app created album is specified, the media items are also added to that album. `albumPosition` is optional and can only be specified if an `albumId` is set.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"newMediaItems\": {\n      \"description\": \"Required. List of media items to be created. Maximum 50 media items per call.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/NewMediaItem\"\n      }\n     },\n     \"albumId\": {\n      \"description\": \"Identifier of the album where the media items are added. The media items are also added to the user's library. This is an optional field.\",\n      \"type\": \"string\"\n     },\n     \"albumPosition\": {\n      \"$ref\": \"#/components/schemas/AlbumPosition\"\n     }\n    }\n   },\n   \"Video\": {\n    \"description\": \"Metadata that is specific to a video, for example, fps and processing status. Some of these fields may be null or not included.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"cameraModel\": {\n      \"description\": \"Model of the camera with which the video was taken.\",\n      \"type\": \"string\"\n     },\n     \"status\": {\n      \"description\": \"Processing status of the video.\",\n      \"type\": \"string\",\n      \"enum\": [\n       \"UNSPECIFIED\",\n       \"PROCESSING\",\n       \"READY\",\n       \"FAILED\"\n      ]\n     },\n     \"cameraMake\": {\n      \"description\": \"Brand of the camera with which the video was taken.\",\n      \"type\": \"string\"\n     },\n     \"fps\": {\n      \"description\": \"Frame rate of the video.\",\n      \"type\": \"number\",\n      \"format\": \"double\"\n     }\n    }\n   },\n   \"ListSharedAlbumsResponse\": {\n    \"description\": \"List of shared albums requested.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"sharedAlbums\": {\n      \"description\": \"Output only. List of shared albums.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Album\"\n      }\n     },\n     \"nextPageToken\": {\n      \"description\": \"Output only. Token to use to get the next set of shared albums. Populated if there are more shared albums to retrieve for this request.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"BatchAddMediaItemsToAlbumResponse\": {\n    \"description\": \"Response for adding media items to an album.\",\n    \"type\": \"object\",\n    \"properties\": {}\n   },\n   \"ShareAlbumResponse\": {\n    \"description\": \"Response to successfully sharing an album.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"shareInfo\": {\n      \"$ref\": \"#/components/schemas/ShareInfo\"\n     }\n    }\n   },\n   \"ContentFilter\": {\n    \"description\": \"This filter allows you to return media items based on the content type. It's possible to specify a list of categories to include, and/or a list of categories to exclude. Within each list, the categories are combined with an OR. The content filter `includedContentCategories`: [c1, c2, c3] would get media items that contain (c1 OR c2 OR c3). The content filter `excludedContentCategories`: [c1, c2, c3] would NOT get media items that contain (c1 OR c2 OR c3). You can also include some categories while excluding others, as in this example: `includedContentCategories`: [c1, c2], `excludedContentCategories`: [c3, c4] The previous example would get media items that contain (c1 OR c2) AND NOT (c3 OR c4). A category that appears in `includedContentategories` must not appear in `excludedContentCategories`.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"includedContentCategories\": {\n      \"description\": \"The set of categories to be included in the media item search results. The items in the set are ORed. There's a maximum of 10 `includedContentCategories` per request.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\",\n       \"enum\": [\n        \"NONE\",\n        \"LANDSCAPES\",\n        \"RECEIPTS\",\n        \"CITYSCAPES\",\n        \"LANDMARKS\",\n        \"SELFIES\",\n        \"PEOPLE\",\n        \"PETS\",\n        \"WEDDINGS\",\n        \"BIRTHDAYS\",\n        \"DOCUMENTS\",\n        \"TRAVEL\",\n        \"ANIMALS\",\n        \"FOOD\",\n        \"SPORT\",\n        \"NIGHT\",\n        \"PERFORMANCES\",\n        \"WHITEBOARDS\",\n        \"SCREENSHOTS\",\n        \"UTILITY\",\n        \"ARTS\",\n        \"CRAFTS\",\n        \"FASHION\",\n        \"HOUSES\",\n        \"GARDENS\",\n        \"FLOWERS\",\n        \"HOLIDAYS\"\n       ]\n      }\n     },\n     \"excludedContentCategories\": {\n      \"description\": \"The set of categories which are not to be included in the media item search results. The items in the set are ORed. There's a maximum of 10 `excludedContentCategories` per request.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\",\n       \"enum\": [\n        \"NONE\",\n        \"LANDSCAPES\",\n        \"RECEIPTS\",\n        \"CITYSCAPES\",\n        \"LANDMARKS\",\n        \"SELFIES\",\n        \"PEOPLE\",\n        \"PETS\",\n        \"WEDDINGS\",\n        \"BIRTHDAYS\",\n        \"DOCUMENTS\",\n        \"TRAVEL\",\n        \"ANIMALS\",\n        \"FOOD\",\n        \"SPORT\",\n        \"NIGHT\",\n        \"PERFORMANCES\",\n        \"WHITEBOARDS\",\n        \"SCREENSHOTS\",\n        \"UTILITY\",\n        \"ARTS\",\n        \"CRAFTS\",\n        \"FASHION\",\n        \"HOUSES\",\n        \"GARDENS\",\n        \"FLOWERS\",\n        \"HOLIDAYS\"\n       ]\n      }\n     }\n    }\n   },\n   \"AddEnrichmentToAlbumRequest\": {\n    \"description\": \"Request to add an enrichment to a specific album at a specific position.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"albumPosition\": {\n      \"$ref\": \"#/components/schemas/AlbumPosition\"\n     },\n     \"newEnrichmentItem\": {\n      \"$ref\": \"#/components/schemas/NewEnrichmentItem\"\n     }\n    }\n   },\n   \"MediaMetadata\": {\n    \"description\": \"Metadata for a media item.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"photo\": {\n      \"$ref\": \"#/components/schemas/Photo\"\n     },\n     \"height\": {\n      \"description\": \"Original height (in pixels) of the media item.\",\n      \"type\": \"string\",\n      \"format\": \"int64\"\n     },\n     \"creationTime\": {\n      \"description\": \"Time when the media item was first created (not when it was uploaded to Google Photos).\",\n      \"type\": \"string\",\n      \"format\": \"google-datetime\"\n     },\n     \"width\": {\n      \"description\": \"Original width (in pixels) of the media item.\",\n      \"type\": \"string\",\n      \"format\": \"int64\"\n     },\n     \"video\": {\n      \"$ref\": \"#/components/schemas/Video\"\n     }\n    }\n   },\n   \"NewMediaItemResult\": {\n    \"description\": \"Result of creating a new media item.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"uploadToken\": {\n      \"description\": \"The upload token used to create this new (simple) media item. Only populated if the media item is simple and required a single upload token.\",\n      \"type\": \"string\"\n     },\n     \"mediaItem\": {\n      \"$ref\": \"#/components/schemas/MediaItem\"\n     },\n     \"status\": {\n      \"$ref\": \"#/components/schemas/Status\"\n     }\n    }\n   },\n   \"SearchMediaItemsRequest\": {\n    \"description\": \"Request to search for app created media items in a user's library. If the album id from an app created album is specified, this call will return the list of media items in the album. If neither filters nor album id are specified, this call will return all app created media items in a user's Google Photos library. If filters are specified, this call will return all app created media items in the user's library that fulfill the filter criteria. Filters and album id must not both be set, as this will result in an invalid request.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"filters\": {\n      \"$ref\": \"#/components/schemas/Filters\"\n     },\n     \"pageSize\": {\n      \"description\": \"Maximum number of media items to return in the response. Fewer media items might be returned than the specified number. The default `pageSize` is 25, the maximum is 100.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     },\n     \"orderBy\": {\n      \"description\": \"An optional field to specify the sort order of the search results. The `orderBy` field only works when a dateFilter is used. When this field is not specified, results are displayed newest first, oldest last by their creationTime. Providing `MediaMetadata.creation_time` displays search results in the opposite order, oldest first then newest last. To display results newest first then oldest last, include the `desc` argument as follows: `MediaMetadata.creation_time desc`. The only additional filters that can be used with this parameter are includeArchivedMedia and excludeNonAppCreatedData. No other filters are supported.\",\n      \"type\": \"string\"\n     },\n     \"pageToken\": {\n      \"description\": \"A continuation token to get the next page of the results. Adding this to the request returns the rows after the `pageToken`. The `pageToken` should be the value returned in the `nextPageToken` parameter in the response to the `searchMediaItems` request.\",\n      \"type\": \"string\"\n     },\n     \"albumId\": {\n      \"description\": \"Identifier of an album. If populated, lists all media items in specified album. Can't set in conjunction with any filters.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"LeaveSharedAlbumResponse\": {\n    \"description\": \"Response to successfully leaving the shared album on behalf of the user.\",\n    \"type\": \"object\",\n    \"properties\": {}\n   },\n   \"ListAlbumsResponse\": {\n    \"description\": \"List of albums requested.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"nextPageToken\": {\n      \"description\": \"Output only. Token to use to get the next set of albums. Populated if there are more albums to retrieve for this request.\",\n      \"type\": \"string\"\n     },\n     \"albums\": {\n      \"description\": \"Output only. List of albums shown in the Albums tab of the user's Google Photos app.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Album\"\n      }\n     }\n    }\n   },\n   \"FeatureFilter\": {\n    \"description\": \"This filter defines the features that the media items should have.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"includedFeatures\": {\n      \"description\": \"The set of features to be included in the media item search results. The items in the set are ORed and may match any of the specified features.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\",\n       \"enum\": [\n        \"NONE\",\n        \"FAVORITES\"\n       ]\n      }\n     }\n    }\n   },\n   \"AlbumPosition\": {\n    \"description\": \"Specifies a position in an album.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"position\": {\n      \"description\": \"Type of position, for a media or enrichment item.\",\n      \"type\": \"string\",\n      \"enum\": [\n       \"POSITION_TYPE_UNSPECIFIED\",\n       \"FIRST_IN_ALBUM\",\n       \"LAST_IN_ALBUM\",\n       \"AFTER_MEDIA_ITEM\",\n       \"AFTER_ENRICHMENT_ITEM\"\n      ]\n     },\n     \"relativeMediaItemId\": {\n      \"description\": \"The media item to which the position is relative to. Only used when position type is AFTER_MEDIA_ITEM.\",\n      \"type\": \"string\"\n     },\n     \"relativeEnrichmentItemId\": {\n      \"description\": \"The enrichment item to which the position is relative to. Only used when position type is AFTER_ENRICHMENT_ITEM.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"JoinSharedAlbumResponse\": {\n    \"description\": \"Response to successfully joining the shared album on behalf of the user.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"album\": {\n      \"$ref\": \"#/components/schemas/Album\"\n     }\n    }\n   },\n   \"BatchRemoveMediaItemsFromAlbumResponse\": {\n    \"description\": \"Response for successfully removing all specified media items from the album.\",\n    \"type\": \"object\",\n    \"properties\": {}\n   },\n   \"UnshareAlbumResponse\": {\n    \"description\": \"Response of a successful unshare of a shared album.\",\n    \"type\": \"object\",\n    \"properties\": {}\n   },\n   \"MediaItem\": {\n    \"description\": \"Representation of a media item (such as a photo or video) in Google Photos.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"mimeType\": {\n      \"description\": \"MIME type of the media item. For example, `image/jpeg`.\",\n      \"type\": \"string\"\n     },\n     \"contributorInfo\": {\n      \"$ref\": \"#/components/schemas/ContributorInfo\"\n     },\n     \"mediaMetadata\": {\n      \"$ref\": \"#/components/schemas/MediaMetadata\"\n     },\n     \"productUrl\": {\n      \"description\": \"Google Photos URL for the media item. This link is available to the user only if they're signed in. When retrieved from an album search, the URL points to the item inside the album.\",\n      \"type\": \"string\"\n     },\n     \"description\": {\n      \"description\": \"Description of the media item. This is shown to the user in the item's info section in the Google Photos app. Must be shorter than 1000 characters. Only include text written by users. Descriptions should add context and help users understand media. Do not include any auto-generated strings such as filenames, tags, and other metadata.\",\n      \"type\": \"string\"\n     },\n     \"id\": {\n      \"description\": \"Identifier for the media item. This is a persistent identifier that can be used between sessions to identify this media item.\",\n      \"type\": \"string\"\n     },\n     \"baseUrl\": {\n      \"description\": \"A URL to the media item's bytes. This shouldn't be used as is. Parameters should be appended to this URL before use. See the [developer documentation](https://developers.google.com/photos/library/guides/access-media-items#base-urls) for a complete list of supported parameters. For example, `'=w2048-h1024'` will set the dimensions of a media item of type photo to have a width of 2048 px and height of 1024 px.\",\n      \"type\": \"string\"\n     },\n     \"filename\": {\n      \"description\": \"Filename of the media item. This is shown to the user in the item's info section in the Google Photos app.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"SharedAlbumOptions\": {\n    \"description\": \"Options that control the sharing of an album.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"isCollaborative\": {\n      \"description\": \"True if the shared album allows collaborators (users who have joined the album) to add media items to it. Defaults to false.\",\n      \"type\": \"boolean\"\n     },\n     \"isCommentable\": {\n      \"description\": \"True if the shared album allows collaborators (users who have joined the album) to add comments to the album. Defaults to false.\",\n      \"type\": \"boolean\"\n     }\n    }\n   },\n   \"LocationEnrichment\": {\n    \"description\": \"An enrichment containing a single location.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"location\": {\n      \"$ref\": \"#/components/schemas/Location\"\n     }\n    }\n   },\n   \"ShareAlbumRequest\": {\n    \"description\": \"Request to make an album shared in Google Photos.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"sharedAlbumOptions\": {\n      \"$ref\": \"#/components/schemas/SharedAlbumOptions\"\n     }\n    }\n   },\n   \"DateFilter\": {\n    \"description\": \"This filter defines the allowed dates or date ranges for the media returned. It's possible to pick a set of specific dates and a set of date ranges. Media items uploaded without metadata specifying the date the media item was captured will not be returned in queries using date filters. Google Photos server upload time is not used as a fallback in this case.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"dates\": {\n      \"description\": \"List of dates that match the media items' creation date. A maximum of 5 dates can be included per request.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/Date\"\n      }\n     },\n     \"ranges\": {\n      \"description\": \"List of dates ranges that match the media items' creation date. A maximum of 5 dates ranges can be included per request.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/DateRange\"\n      }\n     }\n    }\n   },\n   \"AddEnrichmentToAlbumResponse\": {\n    \"description\": \"The enrichment item that's created.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"enrichmentItem\": {\n      \"$ref\": \"#/components/schemas/EnrichmentItem\"\n     }\n    }\n   },\n   \"BatchAddMediaItemsToAlbumRequest\": {\n    \"description\": \"Request to add media items to an app created album.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"mediaItemIds\": {\n      \"description\": \"Required. Identifiers of the MediaItems to be added. The maximum number of media items that can be added in one call is 50.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"string\"\n      }\n     }\n    }\n   },\n   \"Date\": {\n    \"description\": \"Represents a whole calendar date. Set `day` to 0 when only the month and year are significant, for example, all of December 2018. Set `day` and `month` to 0 if only the year is significant, for example, the entire of 2018. Set `year` to 0 when only the day and month are significant, for example, an anniversary or birthday. Unsupported: Setting all values to 0, only `month` to 0, or both `day` and `year` to 0 at the same time.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"month\": {\n      \"description\": \"Month of a year. Must be from 1 to 12, or 0 to specify a year without a month and day.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     },\n     \"year\": {\n      \"description\": \"Year of the date. Must be from 1 to 9999, or 0 to specify a date without a year.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     },\n     \"day\": {\n      \"description\": \"Day of month. Must be from 1 to 31 and valid for the year and month, or 0 if specifying a year/month where the day isn't significant.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     }\n    }\n   },\n   \"LatLng\": {\n    \"description\": \"An object that represents a latitude/longitude pair. This is expressed as a pair of doubles to represent degrees latitude and degrees longitude. Unless specified otherwise, this object must conform to the WGS84 standard. Values must be within normalized ranges.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"longitude\": {\n      \"description\": \"The longitude in degrees. It must be in the range [-180.0, +180.0].\",\n      \"type\": \"number\",\n      \"format\": \"double\"\n     },\n     \"latitude\": {\n      \"description\": \"The latitude in degrees. It must be in the range [-90.0, +90.0].\",\n      \"type\": \"number\",\n      \"format\": \"double\"\n     }\n    }\n   },\n   \"ShareInfo\": {\n    \"description\": \"Information about albums that are shared. This information is only included if you created the album, it is shared and you have the sharing scope.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"isJoined\": {\n      \"description\": \"True if the user is joined to the album. This is always true for the owner of the album.\",\n      \"type\": \"boolean\"\n     },\n     \"sharedAlbumOptions\": {\n      \"$ref\": \"#/components/schemas/SharedAlbumOptions\"\n     },\n     \"isOwned\": {\n      \"description\": \"True if the user owns the album.\",\n      \"type\": \"boolean\"\n     },\n     \"shareToken\": {\n      \"description\": \"A token that is used to join, leave, or retrieve the details of a shared album on behalf of a user who isn't the owner. A `shareToken` is invalidated if the owner turns off link sharing in the Google Photos app, or if the album is unshared.\",\n      \"type\": \"string\"\n     },\n     \"isJoinable\": {\n      \"description\": \"True if the album can be joined by users.\",\n      \"type\": \"boolean\"\n     },\n     \"shareableUrl\": {\n      \"description\": \"A link to the shared Google Photos album. Anyone with the link can view the contents of the album, so it should be treated with care. The `shareableUrl` parameter is only returned if the album has link sharing turned on. If a user is already joined to an album that isn't link-shared, they can use the album's [`productUrl`](https://developers.google.com/photos/library/reference/rest/v1/albums#Album) to access it instead. A `shareableUrl` is invalidated if the owner turns off link sharing in the Google Photos app, or if the album is unshared.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"NewMediaItem\": {\n    \"description\": \"New media item that's created in a user's Google Photos account.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"description\": {\n      \"description\": \"Description of the media item. This is shown to the user in the item's info section in the Google Photos app. Must be shorter than 1000 characters. Only include text written by users. Descriptions should add context and help users understand media. Do not include any auto-generated strings such as filenames, tags, and other metadata.\",\n      \"type\": \"string\"\n     },\n     \"simpleMediaItem\": {\n      \"$ref\": \"#/components/schemas/SimpleMediaItem\"\n     }\n    }\n   },\n   \"MediaItemResult\": {\n    \"description\": \"Result of retrieving a media item.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"status\": {\n      \"$ref\": \"#/components/schemas/Status\"\n     },\n     \"mediaItem\": {\n      \"$ref\": \"#/components/schemas/MediaItem\"\n     }\n    }\n   },\n   \"ListMediaItemsResponse\": {\n    \"description\": \"List of all media items from the user's Google Photos library.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"nextPageToken\": {\n      \"description\": \"Output only. Token to use to get the next set of media items. Its presence is the only reliable indicator of more media items being available in the next request.\",\n      \"type\": \"string\"\n     },\n     \"mediaItems\": {\n      \"description\": \"Output only. List of media items in the user's library.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/MediaItem\"\n      }\n     }\n    }\n   },\n   \"Filters\": {\n    \"description\": \"Filters that can be applied to a media item search. If multiple filter options are specified, they're treated as AND with each other.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"contentFilter\": {\n      \"$ref\": \"#/components/schemas/ContentFilter\"\n     },\n     \"includeArchivedMedia\": {\n      \"description\": \"If set, the results include media items that the user has archived. Defaults to false (archived media items aren't included).\",\n      \"type\": \"boolean\"\n     },\n     \"excludeNonAppCreatedData\": {\n      \"description\": \"If set, the results exclude media items that were not created by this app. Defaults to false (all media items are returned). This field is ignored if the photoslibrary.readonly.appcreateddata scope is used.\",\n      \"type\": \"boolean\"\n     },\n     \"mediaTypeFilter\": {\n      \"$ref\": \"#/components/schemas/MediaTypeFilter\"\n     },\n     \"featureFilter\": {\n      \"$ref\": \"#/components/schemas/FeatureFilter\"\n     },\n     \"dateFilter\": {\n      \"$ref\": \"#/components/schemas/DateFilter\"\n     }\n    }\n   },\n   \"Status\": {\n    \"description\": \"The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors).\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"message\": {\n      \"description\": \"A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the google.rpc.Status.details field, or localized by the client.\",\n      \"type\": \"string\"\n     },\n     \"details\": {\n      \"description\": \"A list of messages that carry the error details. There is a common set of message types for APIs to use.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"type\": \"object\",\n       \"additionalProperties\": {\n        \"description\": \"Properties of the object. Contains field @type with type URL.\"\n       }\n      }\n     },\n     \"code\": {\n      \"description\": \"The status code, which should be an enum value of google.rpc.Code.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     }\n    }\n   },\n   \"ContributorInfo\": {\n    \"description\": \"Information about the user who added the media item. Note that this information is included only if the media item is within a shared album created by your app and you have the sharing scope.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"displayName\": {\n      \"description\": \"Display name of the contributor.\",\n      \"type\": \"string\"\n     },\n     \"profilePictureBaseUrl\": {\n      \"description\": \"URL to the profile picture of the contributor.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"MapEnrichment\": {\n    \"description\": \"An enrichment containing a map, showing origin and destination locations.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"origin\": {\n      \"$ref\": \"#/components/schemas/Location\"\n     },\n     \"destination\": {\n      \"$ref\": \"#/components/schemas/Location\"\n     }\n    }\n   },\n   \"LeaveSharedAlbumRequest\": {\n    \"description\": \"Request to leave a shared album on behalf of the user. This uses a shareToken which can be acquired via the or listSharedAlbums or getAlbum calls.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"shareToken\": {\n      \"description\": \"Required. Token to leave the shared album on behalf of the user.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"EnrichmentItem\": {\n    \"description\": \"An enrichment item.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"id\": {\n      \"description\": \"Identifier of the enrichment item.\",\n      \"type\": \"string\"\n     }\n    }\n   }\n  },\n  \"securitySchemes\": {\n   \"bearer\": {\n    \"type\": \"http\",\n    \"scheme\": \"bearer\"\n   }\n  }\n }\n}\n"},{"path":"products/photos/openapi.ts","content":"// Generated by scripts/google-vendor.ts from packages/google-photos; edit the original and rerun it.\n// openapi.json and picker-openapi.json are generated from Google's official Photos Library API v1\n// and Photos Picker API v1 Discovery documents (https://photoslibrary.googleapis.com/$discovery/rest?version=v1,\n// revision 20261008; https://photospicker.googleapis.com/$discovery/rest?version=v1, revision 20261008) by\n// discovery-to-openapi.mjs; see README. Every operation takes one OAuth bearer token.\nimport type { JsonObject } from \"apps\";\nimport type { OpenapiToolNamesOptions } from \"apps/openapi\";\nimport library from \"./openapi.json\" with { type: \"json\" };\nimport picker from \"./picker-openapi.json\" with { type: \"json\" };\n\n// The inferred JSON type has no index signature, so widen it once here.\nconst widen = (value: unknown): JsonObject => JSON.parse(JSON.stringify(value));\n\nconst common = {\n  securitySchemes: { bearer: { type: \"http\", scheme: \"bearer\" } },\n  methods: {\n    oauth: [{ scheme: \"bearer\", field: \"access_token\", part: \"value\", prefix: \"\" }],\n  },\n  oauth: [],\n} as const;\n\nexport const libraryOptions = {\n  source: { document: widen(library) },\n  allowedOrigin: \"https://photoslibrary.googleapis.com\",\n  ...common,\n  // mediaItems.search and batchGet only read, so they run without an approval prompt.\n  kinds: { \"photoslibrary.mediaItems.search\": \"query\", \"photoslibrary.mediaItems.batchGet\": \"query\" },\n} satisfies OpenapiToolNamesOptions;\n\nexport const pickerOptions = {\n  source: { document: widen(picker) },\n  allowedOrigin: \"https://photospicker.googleapis.com\",\n  ...common,\n} satisfies OpenapiToolNamesOptions;\n\n// scripts/tools.ts reads `options`; it reports the Library spec, pickerOptions is checked separately.\nexport const options = libraryOptions;\n"},{"path":"products/photos/picker-openapi.json","content":"{\n \"openapi\": \"3.0.3\",\n \"info\": {\n  \"title\": \"Google Photos Picker API\",\n  \"version\": \"v1 (discovery revision 20261008)\",\n  \"description\": \"View photos you select from your Google Photos library. \"\n },\n \"servers\": [\n  {\n   \"url\": \"https://photospicker.googleapis.com\"\n  }\n ],\n \"security\": [\n  {\n   \"bearer\": []\n  }\n ],\n \"paths\": {\n  \"/v1/sessions\": {\n   \"post\": {\n    \"operationId\": \"photospicker.sessions.create\",\n    \"description\": \"Generates a new session during which the user can pick photos and videos for third-party access. If the user doesn't have an active Google Photos account, a `FAILED_PRECONDITION` error is returned. If the client application creates too many sessions per user, a `RESOURCE_EXHAUSTED` error is returned. Clients are unlikely to reach these limits under normal circumstances. However, clients are still recommended to call `sessions.delete` after each session, to proactively stay within resource limits. Once [a user taps the **Done**](https://developers.google.com/photos/picker/guides/picking-experience#done_screen) button to complete a picking session, the `pickerUri` will no longer work. Create a new session to allow the user to pick more photos.\",\n    \"parameters\": [\n     {\n      \"name\": \"requestId\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. A client-provided unique identifier for this request. This ID is used to enable the streamlined picking experience for applications using the OAuth 2.0 flow for limited-input devices. This ID must have the format of a UUID (version 4) string and follow these requirements: - Must not contain any sensitive identifying information about the user. - Must contain 32 hexadecimal characters divided into five groups separated by hyphens, in the format \\\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\\\" (or 8-4-4-4-12).\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/PickingSession\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ],\n    \"requestBody\": {\n     \"required\": true,\n     \"content\": {\n      \"application/json\": {\n       \"schema\": {\n        \"$ref\": \"#/components/schemas/PickingSession\"\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/v1/sessions/{sessionsId}\": {\n   \"get\": {\n    \"operationId\": \"photospicker.sessions.get\",\n    \"description\": \"Retrieves information about the specified session. If the specified session does not exist or is not owned by the user, a `NOT_FOUND` error is returned. If the session exists but access to the session has expired, a `PERMISSION_DENIED` error is returned.\",\n    \"parameters\": [\n     {\n      \"name\": \"sessionsId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Identifier segment sessionsId of the resource name.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/PickingSession\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   },\n   \"delete\": {\n    \"operationId\": \"photospicker.sessions.delete\",\n    \"description\": \"Deletes the specified session. A `NOT_FOUND` error is returned if the session does not exist or is not owned by the user. An empty response indicates successful deletion.\",\n    \"parameters\": [\n     {\n      \"name\": \"sessionsId\",\n      \"in\": \"path\",\n      \"required\": true,\n      \"description\": \"Identifier segment sessionsId of the resource name.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/Empty\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  },\n  \"/v1/mediaItems\": {\n   \"get\": {\n    \"operationId\": \"photospicker.mediaItems.list\",\n    \"description\": \"Returns a list of media items picked by the user during the specified session. A `FAILED_PRECONDITION` error is returned if the user has not yet finished picking media items for the specified session. In this scenario, your application should poll `sessions.get` until the session is ready before retrying this method.\",\n    \"parameters\": [\n     {\n      \"name\": \"pageSize\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. The maximum number of media items to return. The service may return fewer than this value (including zero results). If unspecified or set to 0, at most 50 media items is returned. The maximum value is 100; values above 100 will be coerced to 100. Negative values will result in an `INVALID_ARGUMENT` error.\",\n      \"schema\": {\n       \"type\": \"integer\",\n       \"format\": \"int32\"\n      }\n     },\n     {\n      \"name\": \"sessionId\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Required. The Google-generated identifier for this session.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"pageToken\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Optional. A page token, received from a previous `mediaItems.list` call. Provide this to retrieve the subsequent page.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     },\n     {\n      \"name\": \"fields\",\n      \"in\": \"query\",\n      \"required\": false,\n      \"description\": \"Selector specifying which fields to include in a partial response.\",\n      \"schema\": {\n       \"type\": \"string\"\n      }\n     }\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Success\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"$ref\": \"#/components/schemas/ListMediaItemsResponse\"\n        }\n       }\n      }\n     }\n    },\n    \"security\": [\n     {\n      \"bearer\": []\n     }\n    ]\n   }\n  }\n },\n \"components\": {\n  \"schemas\": {\n   \"PickedMediaItem\": {\n    \"description\": \"Representation of a photo or video that was picked by the user.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"type\": {\n      \"description\": \"The type of this media item.\",\n      \"type\": \"string\",\n      \"enum\": [\n       \"TYPE_UNSPECIFIED\",\n       \"PHOTO\",\n       \"VIDEO\"\n      ]\n     },\n     \"id\": {\n      \"description\": \"Identifier for the media item. This is a persistent identifier that can be used between sessions to identify this media item.\",\n      \"type\": \"string\"\n     },\n     \"createTime\": {\n      \"description\": \"Time when the media item was created (not when it was uploaded to Google Photos).\",\n      \"type\": \"string\",\n      \"format\": \"google-datetime\"\n     },\n     \"mediaFile\": {\n      \"$ref\": \"#/components/schemas/MediaFile\"\n     }\n    }\n   },\n   \"Empty\": {\n    \"description\": \"A generic empty message that you can re-use to avoid defining duplicated empty messages in your APIs. A typical example is to use it as the request or the response type of an API method. For instance: service Foo { rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); }\",\n    \"type\": \"object\",\n    \"properties\": {}\n   },\n   \"MediaFileMetadata\": {\n    \"description\": \"Metadata about a media file.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"width\": {\n      \"description\": \"Original width (in pixels) of the media file.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     },\n     \"videoMetadata\": {\n      \"$ref\": \"#/components/schemas/VideoMetadata\"\n     },\n     \"cameraMake\": {\n      \"description\": \"Brand of the camera with which the media was captured.\",\n      \"type\": \"string\"\n     },\n     \"height\": {\n      \"description\": \"Original height (in pixels) of the media file.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     },\n     \"photoMetadata\": {\n      \"$ref\": \"#/components/schemas/PhotoMetadata\"\n     },\n     \"cameraModel\": {\n      \"description\": \"Model of the camera with which the media was captured.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"VideoMetadata\": {\n    \"description\": \"Metadata that is specific to a video. For example, fps.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"processingStatus\": {\n      \"description\": \"Processing status of the video.\",\n      \"type\": \"string\",\n      \"enum\": [\n       \"UNSPECIFIED\",\n       \"PROCESSING\",\n       \"READY\",\n       \"FAILED\"\n      ]\n     },\n     \"fps\": {\n      \"description\": \"Frame rate of the video.\",\n      \"type\": \"number\",\n      \"format\": \"double\"\n     }\n    }\n   },\n   \"PollingConfig\": {\n    \"description\": \"Configuration for polling the API.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"pollInterval\": {\n      \"description\": \"Output only. Recommended time between poll requests.\",\n      \"type\": \"string\",\n      \"format\": \"google-duration\"\n     },\n     \"timeoutIn\": {\n      \"description\": \"Output only. The length of time after which the client should stop polling. A value of 0 indicates that the client should stop polling if it hasn't already.\",\n      \"type\": \"string\",\n      \"format\": \"google-duration\"\n     }\n    }\n   },\n   \"ListMediaItemsResponse\": {\n    \"description\": \"Response to the `mediaItems.list` method.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"mediaItems\": {\n      \"description\": \"A page of picked media items.\",\n      \"type\": \"array\",\n      \"items\": {\n       \"$ref\": \"#/components/schemas/PickedMediaItem\"\n      }\n     },\n     \"nextPageToken\": {\n      \"description\": \"If set, this field can be used as the `pageToken` in a subsequent `mediaItems.list` call to retrieve the next page of picked media items. If this field is omitted, there are no subsequent pages.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"PickingSession\": {\n    \"description\": \"Representation of a user session during which the user can pick photos and videos using Google Photos.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"expireTime\": {\n      \"description\": \"Output only. Time when access to this session (and its picked media items) will expire.\",\n      \"type\": \"string\",\n      \"format\": \"google-datetime\"\n     },\n     \"pickerUri\": {\n      \"description\": \"Output only. The URI used to redirect the user to Google Photos (on web) so they can pick photos and videos for the current session. To view this page successfully, the user must be logged into the Google account that owns this session in their web browser. The `pickerUri` cannot be opened in an iframe due to security reasons. For web-based applications, you can append `/autoclose` to this URI. The Google Photos window or tab will then close automatically after the user has finished picking, instead of displaying a \\\"Done\\\" screen.\",\n      \"type\": \"string\"\n     },\n     \"mediaItemsSet\": {\n      \"description\": \"Output only. If set to `true`, media items have been picked for this session and your application can request the list of picked media items via `mediaItems.list`.\",\n      \"type\": \"boolean\"\n     },\n     \"id\": {\n      \"description\": \"Output only. The Google-generated identifier for this session.\",\n      \"type\": \"string\"\n     },\n     \"pollingConfig\": {\n      \"$ref\": \"#/components/schemas/PollingConfig\"\n     },\n     \"pickingConfig\": {\n      \"$ref\": \"#/components/schemas/PickingConfig\"\n     }\n    }\n   },\n   \"MediaFile\": {\n    \"description\": \"Representation of a media file.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"mediaFileMetadata\": {\n      \"$ref\": \"#/components/schemas/MediaFileMetadata\"\n     },\n     \"filename\": {\n      \"description\": \"Filename of the media file.\",\n      \"type\": \"string\"\n     },\n     \"baseUrl\": {\n      \"description\": \"A URL to fetch the media file's bytes. To download a media file, the API client must add the parameters specified in the developer documentation to this URL. For example, `'=w2048-h1024'` will set the dimensions of a media item of type photo to have a width of 2048 px and height of 1024 px.\",\n      \"type\": \"string\"\n     },\n     \"mimeType\": {\n      \"description\": \"MIME type of the media file. For example, `image/jpeg`.\",\n      \"type\": \"string\"\n     }\n    }\n   },\n   \"PickingConfig\": {\n    \"description\": \"Client-specified configuration for the user's picking experience during this session.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"showExpandedAppBar\": {\n      \"description\": \"Optional. Whether to show an expanded app bar on mobile. If true, the picker will show an app bar with a search bar that is expanded on load instead of a search icon. This will be secured behind an allowlist. UI: https://screenshot.googleplex.com/6dnYtCu95rjzRxX\",\n      \"type\": \"boolean\"\n     },\n     \"showZeroState\": {\n      \"description\": \"Optional. Whether to show a custom zero state page on mobile. If not set, the picker will use the default allphotos emptystate page. This will be secured behind an allowlist. UI: https://screenshot.googleplex.com/eZovEtnzdyWYKHh\",\n      \"type\": \"boolean\"\n     },\n     \"maxItemCount\": {\n      \"description\": \"Optional. The maximum number of items that the user can pick during this session. Defaults to 2000 if not specified. If unspecified or set to 0, at most 2000 items can be picked. Values above 2000 will be coerced to 2000. Negative values will result in an `INVALID_ARGUMENT` error.\",\n      \"type\": \"string\",\n      \"format\": \"int64\"\n     },\n     \"showEducationBanner\": {\n      \"description\": \"Optional. Whether to show an educational banner instead of the partner caption. This will be secured behind an allowlist. UI: https://screenshot.googleplex.com/5TKqW9zkHuuRBwk\",\n      \"type\": \"boolean\"\n     }\n    }\n   },\n   \"PhotoMetadata\": {\n    \"description\": \"Metadata that is specific to a photo, such as, ISO, focal length, and exposure time. Some of these fields may not be set.\",\n    \"type\": \"object\",\n    \"properties\": {\n     \"focalLength\": {\n      \"description\": \"Focal length of the camera lens with which the photo was taken.\",\n      \"type\": \"number\",\n      \"format\": \"float\"\n     },\n     \"isoEquivalent\": {\n      \"description\": \"ISO of the camera with which the photo was taken.\",\n      \"type\": \"integer\",\n      \"format\": \"int32\"\n     },\n     \"apertureFNumber\": {\n      \"description\": \"Aperture f number of the camera lens with which the photo was taken.\",\n      \"type\": \"number\",\n      \"format\": \"float\"\n     },\n     \"exposureTime\": {\n      \"description\": \"Exposure time of the camera aperture when the photo was taken.\",\n      \"type\": \"string\",\n      \"format\": \"google-duration\"\n     }\n    }\n   }\n  },\n  \"securitySchemes\": {\n   \"bearer\": {\n    \"type\": \"http\",\n    \"scheme\": \"bearer\"\n   }\n  }\n }\n}\n"},{"path":"products/sheets/openapi.ts","content":"// Generated by scripts/google-vendor.ts from packages/google-sheets; edit the original and rerun it.\nimport type { OpenapiToolNamesOptions } from \"apps/openapi\";\n\n// APIs.guru's conversion of Google's official Sheets v4 Discovery document. The conversion makes\n// every operation require its \"Oauth2\" and \"Oauth2c\" schemes together; both mean the same bearer\n// access token, so both are declared as bearer and filled from the oauth method's access token.\nexport const options = {\n  source: { url: \"https://api.apis.guru/v2/specs/googleapis.com/sheets/v4/openapi.json\" },\n  allowedOrigin: \"https://sheets.googleapis.com\",\n  securitySchemes: {\n    Oauth2: { type: \"http\", scheme: \"bearer\" },\n    Oauth2c: { type: \"http\", scheme: \"bearer\" },\n  },\n  methods: {\n    oauth: [\n      { scheme: \"Oauth2\", field: \"access_token\", part: \"value\", prefix: \"\" },\n      { scheme: \"Oauth2c\", field: \"access_token\", part: \"value\", prefix: \"\" },\n    ],\n  },\n  kinds: {\n    \"sheets.spreadsheets.developerMetadata.search\": \"query\",\n    \"sheets.spreadsheets.values.batchGetByDataFilter\": \"query\",\n    \"sheets.spreadsheets.getByDataFilter\": \"query\",\n  },\n  oauth: [],\n} satisfies OpenapiToolNamesOptions;\n"},{"path":"products/slides/tools.ts","content":"// Generated by scripts/google-vendor.ts from packages/google-slides; edit the original and rerun it.\n// The tools, without the account: index.ts and packages/google (through scripts/google-vendor.ts) both mount them.\nimport {\n  array,\n  boolean,\n  decodeJson,\n  json,\n  mutation,\n  number,\n  object,\n  query,\n  router,\n  string,\n} from \"apps\";\n\nconst base = \"https://slides.googleapis.com/v1/presentations\";\n\n/** The router's metadata, shared with packages/google. */\nexport const meta = {\n  title: \"Google Slides\",\n  description:\n    \"Read Google Slides presentations as JSON or a text outline, render slide thumbnails, create presentations, and edit them: slides, text, shapes, images, tables, speaker notes and raw batchUpdate requests.\",\n  instructions:\n    \"Call getText or getPresentation first to find slide and element object ids. Sizes and positions are in points (a 16:9 slide is 720 x 405). Text indexes are character offsets from 0. Pass requiredRevisionId (from getPresentation) to fail instead of overwriting concurrent edits.\",\n};\n\ntype Fetch = typeof fetch;\n\nconst presentationId = string({ minLength: 1 });\nconst objectId = string({ minLength: 1 });\nconst Size = { widthPt: number(), heightPt: number() };\nconst Position = { xPt: number(), yPt: number() };\n\nconst transform = (xPt: number, yPt: number) => ({\n  scaleX: 1,\n  scaleY: 1,\n  translateX: xPt,\n  translateY: yPt,\n  unit: \"PT\",\n});\nconst size = (widthPt: number, heightPt: number) => ({\n  width: { magnitude: widthPt, unit: \"PT\" },\n  height: { magnitude: heightPt, unit: \"PT\" },\n});\nconst elementProperties = (pageObjectId: string, widthPt: number, heightPt: number, xPt: number, yPt: number) => ({\n  pageObjectId,\n  size: size(widthPt, heightPt),\n  transform: transform(xPt, yPt),\n});\n\nexport function tools(token: string, fetcher: Fetch, signal: AbortSignal | undefined) {\n  const call = async (path: string, init: { method?: string; body?: unknown; search?: Record<string, string | undefined> } = {}) => {\n    const url = new URL(`${base}${path}`);\n    for (const [key, value] of Object.entries(init.search ?? {})) if (value !== undefined) url.searchParams.set(key, value);\n    const response = await fetcher(url.toString(), {\n      method: init.method ?? \"GET\",\n      signal,\n      headers: { Authorization: `Bearer ${token}`, \"content-type\": \"application/json\" },\n      body: init.body === undefined ? undefined : JSON.stringify(init.body),\n    });\n    return decodeJson(response, json());\n  };\n  const batch = (id: string, requests: unknown[], requiredRevisionId?: string) =>\n    call(`/${encodeURIComponent(id)}:batchUpdate`, {\n      method: \"POST\",\n      body: { requests, ...(requiredRevisionId ? { writeControl: { requiredRevisionId } } : {}) },\n    });\n  const revision = string().optional();\n\n  return router({\n    getPresentation: query(\n      {\n        description:\n          \"Get a presentation as Slides JSON: title, revisionId, page size, slides with every page element, masters and layouts.\",\n        input: object({ presentationId }),\n      },\n      async (_ctx, { presentationId }) => call(`/${encodeURIComponent(presentationId)}`),\n    ),\n    getText: query(\n      {\n        description:\n          \"Get the text on each slide as a compact outline: slide objectId, then each text-bearing element's objectId and text. Use the ids to target edits.\",\n        input: object({ presentationId }),\n      },\n      async (_ctx, { presentationId }) => {\n        const deck = (await call(`/${encodeURIComponent(presentationId)}`)) as Record<string, any>;\n        return {\n          title: deck.title ?? \"\",\n          revisionId: deck.revisionId ?? null,\n          slides: (deck.slides ?? []).map((slide: any, index: number) => ({\n            index,\n            objectId: slide.objectId,\n            elements: textElements(slide.pageElements ?? []),\n          })),\n        };\n      },\n    ),\n    getPage: query(\n      {\n        description: \"Get one page (slide, layout or master) by its object id.\",\n        input: object({ presentationId, pageObjectId: objectId }),\n      },\n      async (_ctx, { presentationId, pageObjectId }) =>\n        call(`/${encodeURIComponent(presentationId)}/pages/${encodeURIComponent(pageObjectId)}`),\n    ),\n    getPageThumbnail: query(\n      {\n        description:\n          \"Render a slide to a PNG thumbnail. Returns a short-lived contentUrl (valid about 30 minutes) plus width and height.\",\n        input: object({\n          presentationId,\n          pageObjectId: objectId,\n          thumbnailSize: string().optional(),\n        }),\n      },\n      async (_ctx, { presentationId, pageObjectId, thumbnailSize }) =>\n        call(`/${encodeURIComponent(presentationId)}/pages/${encodeURIComponent(pageObjectId)}/thumbnail`, {\n          search: {\n            \"thumbnailProperties.mimeType\": \"PNG\",\n            \"thumbnailProperties.thumbnailSize\": thumbnailSize ?? \"LARGE\",\n          },\n        }),\n    ),\n    createPresentation: mutation(\n      {\n        description: \"Create a presentation with the given title. Returns it including its presentationId and first slide.\",\n        input: object({ title: string() }),\n      },\n      async (_ctx, { title }) => call(\"\", { method: \"POST\", body: { title } }),\n    ),\n    batchUpdate: mutation(\n      {\n        description:\n          \"Apply raw presentations.batchUpdate requests (an array of Request objects, e.g. createSlide, insertText, updateShapeProperties). Requests apply in order and are atomic. Use for anything the other tools do not cover.\",\n        input: object({ presentationId, requests: array(json()), requiredRevisionId: revision }),\n      },\n      async (_ctx, { presentationId, requests, requiredRevisionId }) =>\n        batch(presentationId, [...requests], requiredRevisionId),\n    ),\n    createSlide: mutation(\n      {\n        description:\n          \"Add a slide. layout is a predefined layout such as BLANK, TITLE, TITLE_AND_BODY, TITLE_ONLY, SECTION_HEADER, ONE_COLUMN_TEXT, MAIN_POINT, BIG_NUMBER; or pass layoutObjectId for a layout in the deck. insertionIndex defaults to the end.\",\n        input: object({\n          presentationId,\n          layout: string().default(\"BLANK\"),\n          layoutObjectId: string().optional(),\n          insertionIndex: number().optional(),\n          objectId: string().optional(),\n        }),\n      },\n      async (_ctx, { presentationId, layout, layoutObjectId, insertionIndex, objectId }) =>\n        batch(presentationId, [\n          {\n            createSlide: {\n              ...(objectId ? { objectId } : {}),\n              ...(insertionIndex !== undefined ? { insertionIndex } : {}),\n              slideLayoutReference: layoutObjectId ? { layoutId: layoutObjectId } : { predefinedLayout: layout },\n            },\n          },\n        ]),\n    ),\n    duplicateObject: mutation(\n      {\n        description: \"Duplicate a slide or page element. Returns the new object's id in replies.\",\n        input: object({ presentationId, objectId }),\n      },\n      async (_ctx, { presentationId, objectId }) => batch(presentationId, [{ duplicateObject: { objectId } }]),\n    ),\n    deleteObject: mutation(\n      {\n        description: \"Delete a slide or page element by object id.\",\n        input: object({ presentationId, objectId, requiredRevisionId: revision }),\n      },\n      async (_ctx, { presentationId, objectId, requiredRevisionId }) =>\n        batch(presentationId, [{ deleteObject: { objectId } }], requiredRevisionId),\n    ),\n    moveSlides: mutation(\n      {\n        description: \"Move slides (by object id, in their current order) so they start at insertionIndex.\",\n        input: object({ presentationId, slideObjectIds: array(objectId), insertionIndex: number() }),\n      },\n      async (_ctx, { presentationId, slideObjectIds, insertionIndex }) =>\n        batch(presentationId, [{ updateSlidesPosition: { slideObjectIds: [...slideObjectIds], insertionIndex } }]),\n    ),\n    insertText: mutation(\n      {\n        description:\n          \"Insert text into a shape or table cell. insertionIndex is a character offset (0 is the start). For a table cell pass tableRowIndex and tableColumnIndex.\",\n        input: object({\n          presentationId,\n          objectId,\n          text: string(),\n          insertionIndex: number().default(0),\n          tableRowIndex: number().optional(),\n          tableColumnIndex: number().optional(),\n        }),\n      },\n      async (_ctx, { presentationId, objectId, text, insertionIndex, tableRowIndex, tableColumnIndex }) => {\n        if ((tableRowIndex === undefined) !== (tableColumnIndex === undefined)) {\n          throw new Error(\"Provide tableRowIndex and tableColumnIndex together, or neither\");\n        }\n        return batch(presentationId, [\n          {\n            insertText: {\n              objectId,\n              text,\n              insertionIndex,\n              ...(tableRowIndex !== undefined && tableColumnIndex !== undefined\n                ? { cellLocation: { rowIndex: tableRowIndex, columnIndex: tableColumnIndex } }\n                : {}),\n            },\n          },\n        ]);\n      },\n    ),\n    deleteText: mutation(\n      {\n        description:\n          \"Delete text in a shape or table cell. Omit startIndex and endIndex to clear all text; give startIndex (and optionally endIndex) to delete a range.\",\n        input: object({\n          presentationId,\n          objectId,\n          startIndex: number().optional(),\n          endIndex: number().optional(),\n          tableRowIndex: number().optional(),\n          tableColumnIndex: number().optional(),\n        }),\n      },\n      async (_ctx, { presentationId, objectId, startIndex, endIndex, tableRowIndex, tableColumnIndex }) => {\n        if ((tableRowIndex === undefined) !== (tableColumnIndex === undefined)) {\n          throw new Error(\"Provide tableRowIndex and tableColumnIndex together, or neither\");\n        }\n        if (startIndex === undefined && endIndex !== undefined) throw new Error(\"endIndex requires startIndex\");\n        const textRange =\n          startIndex === undefined\n            ? { type: \"ALL\" }\n            : endIndex === undefined\n              ? { type: \"FROM_START_INDEX\", startIndex }\n              : { type: \"FIXED_RANGE\", startIndex, endIndex };\n        return batch(presentationId, [\n          {\n            deleteText: {\n              objectId,\n              textRange,\n              ...(tableRowIndex !== undefined && tableColumnIndex !== undefined\n                ? { cellLocation: { rowIndex: tableRowIndex, columnIndex: tableColumnIndex } }\n                : {}),\n            },\n          },\n        ]);\n      },\n    ),\n    replaceAllText: mutation(\n      {\n        description:\n          \"Replace every occurrence of a string across the deck, or only on the given slides (pageObjectIds).\",\n        input: object({\n          presentationId,\n          find: string({ minLength: 1 }),\n          replaceWith: string(),\n          matchCase: boolean().optional(),\n          pageObjectIds: array(objectId).optional(),\n        }),\n      },\n      async (_ctx, { presentationId, find, replaceWith, matchCase, pageObjectIds }) =>\n        batch(presentationId, [\n          {\n            replaceAllText: {\n              containsText: { text: find, matchCase: matchCase ?? false },\n              replaceText: replaceWith,\n              ...(pageObjectIds && pageObjectIds.length > 0 ? { pageObjectIds: [...pageObjectIds] } : {}),\n            },\n          },\n        ]),\n    ),\n    updateTextStyle: mutation(\n      {\n        description:\n          \"Style text in a shape or table cell. style is a Slides TextStyle (bold, italic, underline, fontSize, fontFamily, foregroundColor, link, ...); fields is the field mask, e.g. \\\"bold,fontSize\\\". Omit startIndex/endIndex to style all text.\",\n        input: object({\n          presentationId,\n          objectId,\n          style: json(),\n          fields: string({ minLength: 1 }),\n          startIndex: number().optional(),\n          endIndex: number().optional(),\n          tableRowIndex: number().optional(),\n          tableColumnIndex: number().optional(),\n        }),\n      },\n      async (_ctx, { presentationId, objectId, style, fields, startIndex, endIndex, tableRowIndex, tableColumnIndex }) => {\n        if ((tableRowIndex === undefined) !== (tableColumnIndex === undefined)) {\n          throw new Error(\"Provide tableRowIndex and tableColumnIndex together, or neither\");\n        }\n        if (startIndex === undefined && endIndex !== undefined) throw new Error(\"endIndex requires startIndex\");\n        const textRange =\n          startIndex === undefined\n            ? { type: \"ALL\" }\n            : endIndex === undefined\n              ? { type: \"FROM_START_INDEX\", startIndex }\n              : { type: \"FIXED_RANGE\", startIndex, endIndex };\n        return batch(presentationId, [\n          {\n            updateTextStyle: {\n              objectId,\n              textRange,\n              style,\n              fields,\n              ...(tableRowIndex !== undefined && tableColumnIndex !== undefined\n                ? { cellLocation: { rowIndex: tableRowIndex, columnIndex: tableColumnIndex } }\n                : {}),\n            },\n          },\n        ]);\n      },\n    ),\n    createShape: mutation(\n      {\n        description:\n          \"Create a shape (TEXT_BOX, RECTANGLE, ROUND_RECTANGLE, ELLIPSE, ARROW_EAST, STAR_5, ...) on a slide. Positions and sizes are in points; a standard 16:9 slide is 720 x 405.\",\n        input: object({\n          presentationId,\n          pageObjectId: objectId,\n          shapeType: string().default(\"TEXT_BOX\"),\n          ...Size,\n          ...Position,\n          objectId: string().optional(),\n        }),\n      },\n      async (_ctx, { presentationId, pageObjectId, shapeType, widthPt, heightPt, xPt, yPt, objectId }) =>\n        batch(presentationId, [\n          {\n            createShape: {\n              ...(objectId ? { objectId } : {}),\n              shapeType,\n              elementProperties: elementProperties(pageObjectId, widthPt, heightPt, xPt, yPt),\n            },\n          },\n        ]),\n    ),\n    createImage: mutation(\n      {\n        description:\n          \"Insert an image from a publicly reachable URL (PNG, JPEG or GIF, under 50 MB) onto a slide. Positions and sizes are in points.\",\n        input: object({\n          presentationId,\n          pageObjectId: objectId,\n          url: string({ minLength: 1 }),\n          ...Size,\n          ...Position,\n          objectId: string().optional(),\n        }),\n      },\n      async (_ctx, { presentationId, pageObjectId, url, widthPt, heightPt, xPt, yPt, objectId }) =>\n        batch(presentationId, [\n          {\n            createImage: {\n              ...(objectId ? { objectId } : {}),\n              url,\n              elementProperties: elementProperties(pageObjectId, widthPt, heightPt, xPt, yPt),\n            },\n          },\n        ]),\n    ),\n    createTable: mutation(\n      {\n        description: \"Create an empty table on a slide. Positions and sizes are in points.\",\n        input: object({\n          presentationId,\n          pageObjectId: objectId,\n          rows: number(),\n          columns: number(),\n          ...Size,\n          ...Position,\n          objectId: string().optional(),\n        }),\n      },\n      async (_ctx, { presentationId, pageObjectId, rows, columns, widthPt, heightPt, xPt, yPt, objectId }) =>\n        batch(presentationId, [\n          {\n            createTable: {\n              ...(objectId ? { objectId } : {}),\n              rows,\n              columns,\n              elementProperties: elementProperties(pageObjectId, widthPt, heightPt, xPt, yPt),\n            },\n          },\n        ]),\n    ),\n    updatePageElementTransform: mutation(\n      {\n        description: \"Move or scale an element. applyMode is ABSOLUTE (replace the transform) or RELATIVE (compose with it). Translation is in points.\",\n        input: object({\n          presentationId,\n          objectId,\n          xPt: number(),\n          yPt: number(),\n          scaleX: number().default(1),\n          scaleY: number().default(1),\n          applyMode: string().default(\"ABSOLUTE\"),\n        }),\n      },\n      async (_ctx, { presentationId, objectId, xPt, yPt, scaleX, scaleY, applyMode }) =>\n        batch(presentationId, [\n          {\n            updatePageElementTransform: {\n              objectId,\n              applyMode,\n              transform: { scaleX, scaleY, translateX: xPt, translateY: yPt, unit: \"PT\" },\n            },\n          },\n        ]),\n    ),\n    updateSpeakerNotes: mutation(\n      {\n        description:\n          \"Replace the speaker notes of a slide. notesObjectId is slide.slideProperties.notesPage.notesProperties.speakerNotesObjectId from getPresentation.\",\n        input: object({ presentationId, notesObjectId: objectId, text: string() }),\n      },\n      async (_ctx, { presentationId, notesObjectId, text }) =>\n        batch(presentationId, [\n          { deleteText: { objectId: notesObjectId, textRange: { type: \"ALL\" } } },\n          ...(text.length > 0 ? [{ insertText: { objectId: notesObjectId, text, insertionIndex: 0 } }] : []),\n        ]),\n    ),\n  });\n}\n\nfunction textElements(elements: any[]): { objectId: string; text: string }[] {\n  const out: { objectId: string; text: string }[] = [];\n  for (const element of elements) {\n    if (element.shape?.text) {\n      out.push({ objectId: element.objectId, text: runsToText(element.shape.text.textElements ?? []) });\n    } else if (element.table) {\n      const cells: string[] = [];\n      for (const row of element.table.tableRows ?? [])\n        cells.push((row.tableCells ?? []).map((c: any) => runsToText(c.text?.textElements ?? []).trim()).join(\" | \"));\n      out.push({ objectId: element.objectId, text: cells.join(\"\\n\") });\n    } else if (element.elementGroup) {\n      out.push(...textElements(element.elementGroup.children ?? []));\n    }\n  }\n  return out.filter((e) => e.text.length > 0);\n}\n\nfunction runsToText(runs: any[]): string {\n  return runs.map((r) => r.textRun?.content ?? \"\").join(\"\");\n}\n"},{"path":"products/tasks/openapi.ts","content":"// Generated by scripts/google-vendor.ts from packages/google-tasks; edit the original and rerun it.\nimport type { OpenapiToolNamesOptions } from \"apps/openapi\";\n\n// APIs.guru's conversion of Google's official Tasks v1 Discovery document. The conversion makes\n// every operation require its \"Oauth2\" and \"Oauth2c\" schemes together; both mean the same bearer\n// access token, so both are declared as bearer and filled from the oauth method's access token.\nexport const options = {\n  source: { url: \"https://api.apis.guru/v2/specs/googleapis.com/tasks/v1/openapi.json\" },\n  allowedOrigin: \"https://tasks.googleapis.com\",\n  securitySchemes: {\n    Oauth2: { type: \"http\", scheme: \"bearer\" },\n    Oauth2c: { type: \"http\", scheme: \"bearer\" },\n  },\n  methods: {\n    oauth: [\n      { scheme: \"Oauth2\", field: \"access_token\", part: \"value\", prefix: \"\" },\n      { scheme: \"Oauth2c\", field: \"access_token\", part: \"value\", prefix: \"\" },\n    ],\n  },\n  oauth: [],\n} satisfies OpenapiToolNamesOptions;\n"},{"path":"provider.ts","content":"import { decodeJson, defineProvider, oauth2, object, string } from \"apps\";\n\nconst Profile = object({ emailAddress: string() });\n\n// Every scope here is on Executor for Google's allowlist, so Executor Cloud can offer its hosted\n// client. Google Chat is left out: its chat.* scopes are not on that list.\nexport const google = defineProvider({\n  name: \"Google\",\n  hosts: [\n    \"gmail.googleapis.com\",\n    \"www.googleapis.com\",\n    \"sheets.googleapis.com\",\n    \"docs.googleapis.com\",\n    \"slides.googleapis.com\",\n    \"forms.googleapis.com\",\n    \"tasks.googleapis.com\",\n    \"people.googleapis.com\",\n    \"meet.googleapis.com\",\n    \"photoslibrary.googleapis.com\",\n    \"photospicker.googleapis.com\",\n  ],\n  auth: {\n    // Google offers no client registration: the connect page asks for an OAuth client.\n    oauth: oauth2({\n      discover: \"https://accounts.google.com\",\n      scopes: [\n        \"openid\",\n        \"email\",\n        \"profile\",\n        \"https://mail.google.com/\",\n        \"https://www.googleapis.com/auth/gmail.settings.basic\",\n        \"https://www.googleapis.com/auth/calendar\",\n        \"https://www.googleapis.com/auth/drive\",\n        \"https://www.googleapis.com/auth/spreadsheets\",\n        \"https://www.googleapis.com/auth/documents\",\n        \"https://www.googleapis.com/auth/presentations\",\n        \"https://www.googleapis.com/auth/forms.body\",\n        \"https://www.googleapis.com/auth/forms.responses.readonly\",\n        \"https://www.googleapis.com/auth/tasks\",\n        \"https://www.googleapis.com/auth/contacts\",\n        \"https://www.googleapis.com/auth/contacts.other.readonly\",\n        \"https://www.googleapis.com/auth/directory.readonly\",\n        \"https://www.googleapis.com/auth/meetings.space.created\",\n        \"https://www.googleapis.com/auth/meetings.space.readonly\",\n        \"https://www.googleapis.com/auth/meetings.space.settings\",\n        \"https://www.googleapis.com/auth/photoslibrary.appendonly\",\n        \"https://www.googleapis.com/auth/photoslibrary.readonly.appcreateddata\",\n        \"https://www.googleapis.com/auth/photoslibrary.edit.appcreateddata\",\n        \"https://www.googleapis.com/auth/photospicker.mediaitems.readonly\",\n      ],\n      // Google issues refresh tokens only when asked for offline access.\n      authorizationParams: { access_type: \"offline\", prompt: \"consent\" },\n    }),\n  },\n  async health({ account, fetch, signal }) {\n    const response = await fetch(\"https://gmail.googleapis.com/gmail/v1/users/me/profile\", {\n      signal,\n      headers: { Authorization: `Bearer ${account.fields.access_token}` },\n    });\n    const me = await decodeJson(response, Profile);\n    return { accountInfo: { externalId: me.emailAddress, email: me.emailAddress } };\n  },\n});\n\n/** The app's requirements, shared by index.ts and the curated tools. */\nexport const requirements = { user: { accounts: { google: google.many() } } };\n"},{"path":"tools/calendar.ts","content":"// Generated by scripts/google-vendor.ts from shared/google-tools; edit the original and rerun it.\n// Calendar tools shaped for agents: one agenda across every calendar of every linked account,\n// combined availability with free slots, and event writes that take plain fields.\nimport { array, boolean, mutation, number, object, query, string } from \"apps\";\nimport { always } from \"apps/operations/approval\";\nimport {\n  calendarZone,\n  defined,\n  fanOut,\n  google,\n  parseTime,\n  select,\n  single,\n  zonedDate,\n  zonedTime,\n  type Base,\n  type Context,\n  type Source,\n  type Target,\n  type WriteContext,\n} from \"./shared.js\";\n\nconst base = \"https://www.googleapis.com/calendar/v3\";\nconst account = string().optional();\nconst day = 24 * 60 * 60 * 1000;\n\ninterface CalendarEntry {\n  readonly id: string;\n  readonly summary?: string;\n  readonly summaryOverride?: string;\n  readonly primary?: boolean;\n  readonly selected?: boolean;\n  readonly hidden?: boolean;\n  readonly accessRole?: string;\n}\n\n/** The calendars shown in the account's Calendar UI: selected and not hidden. */\nconst shown = async (ctx: Base, target: Target, calendarIds: readonly string[] | undefined) => {\n  const { items = [] } = await google(ctx, target, `${base}/users/me/calendarList`, { search: { maxResults: 250 } });\n  const all = items as CalendarEntry[];\n  if (calendarIds?.length) return all.filter((entry) => calendarIds.includes(entry.id) || (entry.primary && calendarIds.includes(\"primary\")));\n  return all.filter((entry) => entry.primary || (entry.selected && !entry.hidden));\n};\n\n/** A window from inputs a model passes: `from`/`to`, or `days` from `from` (default today), read in `zone`. */\nconst window = (zone: string, input: { readonly from?: string; readonly to?: string; readonly days?: number }) => {\n  const start = parseTime(input.from ?? \"now\", zone);\n  if (input.to) return { start, end: parseTime(input.to, zone) };\n  const date = zonedDate(zone, start);\n  return { start, end: zonedTime(zone, date.year, date.month, date.day + (input.days ?? 7)) };\n};\n\nconst self = (event: any) => event.attendees?.find((attendee: any) => attendee.self);\n\nconst event = (target: Target, calendar: CalendarEntry, item: any) =>\n  defined({\n    account: target.email,\n    calendarId: calendar.id,\n    calendar: calendar.summaryOverride ?? calendar.summary ?? calendar.id,\n    eventId: item.id as string,\n    summary: (item.summary as string | undefined) ?? \"(no title)\",\n    start: (item.start?.dateTime ?? item.start?.date) as string,\n    end: (item.end?.dateTime ?? item.end?.date) as string,\n    allDay: item.start?.date !== undefined,\n    location: item.location as string | undefined,\n    meetLink: (item.hangoutLink ?? item.conferenceData?.entryPoints?.find((e: any) => e.entryPointType === \"video\")?.uri) as string | undefined,\n    organizer: item.organizer?.email as string | undefined,\n    attendees: (item.attendees?.length ?? 0) as number,\n    myResponse: self(item)?.responseStatus as string | undefined,\n    status: item.status as string,\n    link: item.htmlLink as string,\n    iCalUID: item.iCalUID as string,\n  });\n\nconst sortKey = (start: string) => (start.length === 10 ? Date.parse(`${start}T00:00:00Z`) : Date.parse(start));\n\nconst busyWindows = async (ctx: Base, targets: readonly Target[], start: number, end: number) =>\n  fanOut(targets, async (target) => {\n    const calendars = await shown(ctx, target, undefined);\n    const result = await google(ctx, target, `${base}/freeBusy`, {\n      method: \"POST\",\n      body: {\n        timeMin: new Date(start).toISOString(),\n        timeMax: new Date(end).toISOString(),\n        // Other people's calendars a user has merely subscribed to are not their own commitments.\n        items: calendars.filter((c) => c.primary || c.accessRole === \"owner\").map((c) => ({ id: c.id })),\n      },\n    });\n    return Object.values(result.calendars ?? {}).flatMap((calendar: any) =>\n      (calendar.busy ?? []).map((busy: { start: string; end: string }) => ({\n        account: target.email,\n        start: Date.parse(busy.start),\n        end: Date.parse(busy.end),\n      })),\n    );\n  });\n\nconst merge = (intervals: readonly { readonly start: number; readonly end: number }[]) => {\n  const sorted = [...intervals].sort((a, b) => a.start - b.start);\n  const merged: { start: number; end: number }[] = [];\n  for (const interval of sorted) {\n    const last = merged.at(-1);\n    if (last && interval.start <= last.end) last.end = Math.max(last.end, interval.end);\n    else merged.push({ start: interval.start, end: interval.end });\n  }\n  return merged;\n};\n\nconst iso = (zone: string, instant: number) => {\n  const text = new Intl.DateTimeFormat(\"sv-SE\", {\n    timeZone: zone,\n    year: \"numeric\",\n    month: \"2-digit\",\n    day: \"2-digit\",\n    hour: \"2-digit\",\n    minute: \"2-digit\",\n    hourCycle: \"h23\",\n  }).format(new Date(instant));\n  return text.replace(\" \", \"T\");\n};\n\n/** Events across targets' shown calendars, sorted, with shared meetings listed once. */\nexport const listEvents = async (\n  ctx: Base,\n  targets: readonly Target[],\n  start: number,\n  end: number,\n  text?: string,\n  calendarIds?: readonly string[],\n) => {\n  const { items, errors } = await fanOut(targets, async (target) => {\n    const calendars = await shown(ctx, target, calendarIds);\n    const lists = await Promise.all(\n      calendars.map(async (calendar) => {\n        const { items = [] } = await google(ctx, target, `${base}/calendars/${encodeURIComponent(calendar.id)}/events`, {\n          search: {\n            timeMin: new Date(start).toISOString(),\n            timeMax: new Date(end).toISOString(),\n            singleEvents: true,\n            orderBy: \"startTime\",\n            maxResults: 250,\n            q: text,\n          },\n        });\n        return (items as any[]).filter((item) => item.status !== \"cancelled\").map((item) => event(target, calendar, item));\n      }),\n    );\n    return lists.flat();\n  });\n  const seen = new Set<string>();\n  const events = items\n    .sort((a, b) => sortKey(a.start) - sortKey(b.start))\n    .filter((item) => {\n      const key = `${item.iCalUID}|${item.start}`;\n      if (seen.has(key)) return false;\n      seen.add(key);\n      return true;\n    })\n    .map(({ iCalUID: _, ...item }) => item);\n  return { events, errors };\n};\n\n/** The curated tools and their router's metadata; `source` names the package's accounts. */\nexport const calendar = (source: Source) => ({\n  tools: {\n    agenda: query(\n      {\n        description:\n          \"List events across every calendar shown in each linked account's Google Calendar (or one account), merged and sorted by start time. Defaults to the next 7 days from now. Shared meetings that appear in several accounts are listed once. Optionally filter by free text (title, description, location, attendees).\",\n        input: object({\n          account,\n          from: string().optional(),\n          to: string().optional(),\n          days: number().optional(),\n          query: string().optional(),\n          calendarIds: array(string()).optional(),\n          timeZone: string().optional(),\n        }),\n      },\n      async (ctx: Context, input) => {\n        const targets = await select(ctx, source, input.account);\n        const zone = input.timeZone ?? (await calendarZone(ctx, targets[0]!));\n        const { start, end } = window(zone, input);\n        const { events, errors } = await listEvents(ctx, targets, start, end, input.query, input.calendarIds);\n        return { timeZone: zone, from: new Date(start).toISOString(), to: new Date(end).toISOString(), events, errors };\n      },\n    ),\n    freeBusy: query(\n      {\n        description:\n          \"Combined availability across every linked account (or one): busy intervals merged from each account's own calendars, and free slots of at least `minutes` within working hours (default 09:00-17:00 on weekdays, in the calendar's time zone). Use it to find a time that works across work and personal calendars.\",\n        input: object({\n          account,\n          from: string().optional(),\n          to: string().optional(),\n          days: number().optional(),\n          minutes: number().optional(),\n          dayStart: string().optional(),\n          dayEnd: string().optional(),\n          includeWeekends: boolean().optional(),\n          timeZone: string().optional(),\n        }),\n      },\n      async (ctx: Context, input) => {\n        const targets = await select(ctx, source, input.account);\n        const zone = input.timeZone ?? (await calendarZone(ctx, targets[0]!));\n        const { start, end } = window(zone, input);\n        const { items, errors } = await busyWindows(ctx, targets, start, end);\n        const busy = merge(items);\n        const [startHour, startMinute] = (input.dayStart ?? \"09:00\").split(\":\").map(Number) as [number, number];\n        const [endHour, endMinute] = (input.dayEnd ?? \"17:00\").split(\":\").map(Number) as [number, number];\n        const minimum = (input.minutes ?? 30) * 60 * 1000;\n        const free: { start: string; end: string; minutes: number }[] = [];\n        for (let cursor = start; cursor < end; cursor += day) {\n          const date = zonedDate(zone, cursor);\n          const weekday = new Date(Date.UTC(date.year, date.month - 1, date.day)).getUTCDay();\n          if (!input.includeWeekends && (weekday === 0 || weekday === 6)) continue;\n          let from = Math.max(start, zonedTime(zone, date.year, date.month, date.day, startHour, startMinute ?? 0));\n          const until = Math.min(end, zonedTime(zone, date.year, date.month, date.day, endHour, endMinute ?? 0));\n          for (const interval of busy) {\n            if (interval.end <= from || interval.start >= until) continue;\n            if (interval.start - from >= minimum) free.push({ start: iso(zone, from), end: iso(zone, interval.start), minutes: (interval.start - from) / 60000 });\n            from = Math.max(from, interval.end);\n          }\n          if (until - from >= minimum) free.push({ start: iso(zone, from), end: iso(zone, until), minutes: (until - from) / 60000 });\n        }\n        return {\n          timeZone: zone,\n          accounts: targets.map((t) => t.email),\n          busy: busy.map((b) => ({ start: iso(zone, b.start), end: iso(zone, b.end) })),\n          free,\n          errors,\n        };\n      },\n    ),\n    calendars: query(\n      {\n        description: \"List every linked account's calendars with their IDs, access role and whether they are shown.\",\n        input: object({ account }),\n      },\n      async (ctx: Context, input) =>\n        fanOut(await select(ctx, source, input.account), async (target) => {\n          const { items = [] } = await google(ctx, target, `${base}/users/me/calendarList`, { search: { maxResults: 250 } });\n          return (items as CalendarEntry[]).map((c) => ({\n            account: target.email,\n            calendarId: c.id,\n            name: c.summaryOverride ?? c.summary ?? c.id,\n            primary: c.primary ?? false,\n            shown: c.primary || (c.selected === true && !c.hidden),\n            accessRole: c.accessRole,\n          })).map(defined);\n        }).then(({ items, errors }) => ({ calendars: items, errors })),\n    ),\n    createEvent: mutation(\n      {\n        description:\n          \"Create an event. start and end take RFC 3339 times, local times (2026-10-14T15:00, read in the calendar's zone) or dates for an all-day event (end is the day after the last day). Set meet to add a Google Meet link; attendees get invitations.\",\n        input: object({\n          account,\n          calendarId: string().optional(),\n          summary: string(),\n          start: string(),\n          end: string().optional(),\n          minutes: number().optional(),\n          description: string().optional(),\n          location: string().optional(),\n          attendees: array(string()).optional(),\n          meet: boolean().optional(),\n          timeZone: string().optional(),\n        }),\n        approval: always(),\n      },\n      async (ctx: WriteContext, input) => {\n        const target = await single(ctx, source, input.account);\n        const zone = input.timeZone ?? (await calendarZone(ctx, target));\n        const allDay = /^\\d{4}-\\d{2}-\\d{2}$/.test(input.start.trim());\n        const when = (value: string) => (allDay ? { date: value.trim() } : { dateTime: new Date(parseTime(value, zone)).toISOString(), timeZone: zone });\n        const startAt = parseTime(input.start, zone);\n        const end = input.end\n          ? when(input.end)\n          : allDay\n            ? (() => {\n                const next = zonedDate(\"UTC\", Date.parse(`${input.start.trim()}T00:00:00Z`) + day);\n                return { date: `${next.year}-${String(next.month).padStart(2, \"0\")}-${String(next.day).padStart(2, \"0\")}` };\n              })()\n            : { dateTime: new Date(startAt + (input.minutes ?? 30) * 60000).toISOString(), timeZone: zone };\n        const created = await google(ctx, target, `${base}/calendars/${encodeURIComponent(input.calendarId ?? \"primary\")}/events`, {\n          method: \"POST\",\n          search: { conferenceDataVersion: input.meet ? 1 : undefined, sendUpdates: input.attendees?.length ? \"all\" : undefined },\n          body: {\n            summary: input.summary,\n            description: input.description,\n            location: input.location,\n            start: when(input.start),\n            end,\n            attendees: input.attendees?.map((email) => ({ email })),\n            ...(input.meet\n              ? { conferenceData: { createRequest: { requestId: crypto.randomUUID(), conferenceSolutionKey: { type: \"hangoutsMeet\" } } } }\n              : {}),\n          },\n        });\n        const { iCalUID: _, ...summary } = event(target, { id: input.calendarId ?? \"primary\" }, created);\n        return summary;\n      },\n    ),\n    respond: mutation(\n      {\n        description: 'Answer an invitation: response is \"accepted\", \"declined\" or \"tentative\", optionally with a note to the organizer.',\n        input: object({\n          account,\n          calendarId: string().optional(),\n          eventId: string({ minLength: 1 }),\n          response: string(),\n          comment: string().optional(),\n        }),\n        approval: always(),\n      },\n      async (ctx: WriteContext, input) => {\n        const target = await single(ctx, source, input.account);\n        const path = `${base}/calendars/${encodeURIComponent(input.calendarId ?? \"primary\")}/events/${encodeURIComponent(input.eventId)}`;\n        const current = await google(ctx, target, path);\n        const me = (current.attendees ?? []).find((a: any) => a.self || a.email?.toLowerCase() === target.email.toLowerCase());\n        if (!me) throw new Error(`${target.email} is not an attendee of this event.`);\n        const status = input.response.trim().toLowerCase();\n        if (![\"accepted\", \"declined\", \"tentative\"].includes(status)) throw new Error('response must be \"accepted\", \"declined\" or \"tentative\".');\n        const attendees = current.attendees.map((a: any) => (a === me ? { ...a, responseStatus: status, ...(input.comment ? { comment: input.comment } : {}) } : a));\n        await google(ctx, target, path, { method: \"PATCH\", search: { sendUpdates: \"all\" }, body: { attendees } });\n        return { account: target.email, eventId: input.eventId, response: status };\n      },\n    ),\n  },\n  meta: {\n    title: \"Google Calendar\",\n    description: \"Agenda and availability across every linked Google account, and simple event writes.\",\n    instructions: `agenda and freeBusy span every linked account unless \\`account\\` (an address) is given. Times without an offset are read in the account's Calendar time zone. Event edits, recurrence and sharing are under ${source.api(\"calendar\")}.`,\n  },\n});\n"},{"path":"tools/drive.ts","content":"// Generated by scripts/google-vendor.ts from shared/google-tools; edit the original and rerun it.\n// Drive tools shaped for agents: search across every linked account in plain words, and read any\n// file as text, exporting Google Docs, Sheets and Slides on the way.\nimport { number, object, query, string } from \"apps\";\nimport { defined, fanOut, google, googleText, select, single, type Base, type Context, type Source, type Target } from \"./shared.js\";\n\nconst base = \"https://www.googleapis.com/drive/v3\";\nconst account = string().optional();\nconst fields = \"id,name,mimeType,modifiedTime,size,webViewLink,owners(emailAddress),parents,shared\";\n\nconst kinds: Record<string, string> = {\n  doc: \"application/vnd.google-apps.document\",\n  sheet: \"application/vnd.google-apps.spreadsheet\",\n  slides: \"application/vnd.google-apps.presentation\",\n  form: \"application/vnd.google-apps.form\",\n  folder: \"application/vnd.google-apps.folder\",\n  pdf: \"application/pdf\",\n};\n\nconst quote = (text: string) => `'${text.replaceAll(\"\\\\\", \"\\\\\\\\\").replaceAll(\"'\", \"\\\\'\")}'`;\n\n/** Drive query language passes through; plain words search names and contents. */\nconst driveQuery = (text: string | undefined, kind: string | undefined) => {\n  const clauses = [\"trashed = false\"];\n  const trimmed = text?.trim();\n  if (trimmed) {\n    const raw = /\\b(contains|in parents|in owners|mimeType|modifiedTime|sharedWithMe|starred)\\b|[=<>]/.test(trimmed);\n    clauses.push(raw ? `(${trimmed})` : `(name contains ${quote(trimmed)} or fullText contains ${quote(trimmed)})`);\n  }\n  if (kind) {\n    const mimeType = kinds[kind];\n    if (mimeType === undefined) throw new Error(`type must be one of ${Object.keys(kinds).join(\", \")}.`);\n    clauses.push(`mimeType = ${quote(mimeType)}`);\n  }\n  return clauses.join(\" and \");\n};\n\nconst file = (target: Target, item: any) =>\n  defined({\n    account: target.email,\n    fileId: item.id as string,\n    name: item.name as string,\n    type: (Object.entries(kinds).find(([, mime]) => mime === item.mimeType)?.[0] ?? item.mimeType) as string,\n    modified: item.modifiedTime as string,\n    owner: item.owners?.[0]?.emailAddress as string | undefined,\n    size: item.size === undefined ? undefined : Number(item.size),\n    link: item.webViewLink as string,\n  });\n\n/** Exports for Google's own formats; other files download as they are. */\nconst exports: Record<string, string> = {\n  \"application/vnd.google-apps.document\": \"text/markdown\",\n  \"application/vnd.google-apps.spreadsheet\": \"text/csv\",\n  \"application/vnd.google-apps.presentation\": \"text/plain\",\n  \"application/vnd.google-apps.drawing\": \"image/svg+xml\",\n  \"application/vnd.google-apps.script\": \"application/vnd.google-apps.script+json\",\n};\nconst readable = /^(text\\/|application\\/(json|xml|javascript|x-yaml|yaml|csv|sql|x-sh))|\\+(json|xml)$/;\n\nconst readFile = async (ctx: Base, target: Target, fileId: string, maxCharacters: number) => {\n  const id = encodeURIComponent(fileId);\n  const meta = await google(ctx, target, `${base}/files/${id}`, { search: { fields, supportsAllDrives: true } });\n  const exportType = exports[meta.mimeType];\n  let text: string;\n  if (exportType) {\n    try {\n      text = await googleText(ctx, target, `${base}/files/${id}/export?mimeType=${encodeURIComponent(exportType)}`);\n    } catch (error) {\n      // Markdown export is newer than plain text; fall back where it is refused.\n      if (exportType !== \"text/markdown\") throw error;\n      text = await googleText(ctx, target, `${base}/files/${id}/export?mimeType=text/plain`);\n    }\n  } else if (readable.test(meta.mimeType)) {\n    text = await googleText(ctx, target, `${base}/files/${id}?alt=media&supportsAllDrives=true`);\n  } else {\n    return { ...file(target, meta), text: null, note: `${meta.mimeType} is not text; open the link or use api.drive to download it.` };\n  }\n  return {\n    ...file(target, meta),\n    ...(meta.mimeType === \"application/vnd.google-apps.spreadsheet\" ? { note: \"Only the first sheet is exported; use sheets.read for others.\" } : {}),\n    truncated: text.length > maxCharacters,\n    text: text.slice(0, maxCharacters),\n  };\n};\n\n/** Files matching a Drive query across targets, newest first. */\nexport const searchFiles = async (ctx: Base, targets: readonly Target[], q: string, max: number) => {\n  const { items, errors } = await fanOut(targets, async (target) => {\n    const { files = [] } = await google(ctx, target, `${base}/files`, {\n      search: {\n        q,\n        pageSize: max,\n        // Drive refuses ordering a fullText search.\n        orderBy: q.includes(\"fullText\") ? undefined : \"modifiedTime desc\",\n        fields: `files(${fields})`,\n        corpora: \"allDrives\",\n        includeItemsFromAllDrives: true,\n        supportsAllDrives: true,\n      },\n    });\n    return (files as any[]).map((item) => file(target, item));\n  });\n  items.sort((a, b) => b.modified.localeCompare(a.modified));\n  return { files: items.slice(0, max), errors };\n};\n\n/** The curated tools and their router's metadata; `source` names the package's accounts. */\nexport const drive = (source: Source) => ({\n  tools: {\n    search: query(\n      {\n        description:\n          \"Search Drive across every linked Google account (or one), newest first. Plain words match file names and contents; Drive query syntax (name contains 'x', mimeType = '...', 'me' in owners, sharedWithMe) passes through. Leave query empty for recently modified files. type narrows to doc, sheet, slides, form, folder or pdf.\",\n        input: object({\n          query: string().optional(),\n          type: string().optional(),\n          account,\n          max: number().optional(),\n        }),\n      },\n      async (ctx: Context, input) =>\n        searchFiles(ctx, await select(ctx, source, input.account), driveQuery(input.query, input.type), Math.min(Math.max(input.max ?? 20, 1), 100)),\n    ),\n    read: query(\n      {\n        description:\n          \"Read a Drive file as text: Google Docs as Markdown, Sheets as CSV (first sheet), Slides as text, and text-like files as they are. Other files return their details and link. Long files are cut at maxCharacters (default 100000).\",\n        input: object({ account, fileId: string({ minLength: 1 }), maxCharacters: number().optional() }),\n      },\n      async (ctx: Context, input) => readFile(ctx, await single(ctx, source, input.account), input.fileId, input.maxCharacters ?? 100_000),\n    ),\n  },\n  meta: {\n    title: \"Google Drive\",\n    description: \"Find and read files across every linked Google account.\",\n    instructions: `search spans every linked account unless \\`account\\` (an address) is given; read takes the account a result came from. Uploads, sharing, comments and revisions are under ${source.api(\"drive\")}.`,\n  },\n});\n\nexport { driveQuery };\n"},{"path":"tools/gmail.ts","content":"// Generated by scripts/google-vendor.ts from shared/google-tools; edit the original and rerun it.\n// Gmail tools shaped for agents: search returns readable thread summaries across every linked\n// account, reads return decoded text, and writes take plain fields instead of raw MIME.\nimport { array, boolean, mutation, number, object, query, string } from \"apps\";\nimport { always } from \"apps/operations/approval\";\nimport {\n  base64Lines,\n  base64url,\n  decodeBody,\n  encodeHeader,\n  fanOut,\n  google,\n  htmlToText,\n  mapLimit,\n  select,\n  single,\n  type Base,\n  type Context,\n  type Source,\n  type Target,\n  type WriteContext,\n} from \"./shared.js\";\n\nconst base = \"https://gmail.googleapis.com/gmail/v1/users/me\";\nconst account = string().optional();\n\ninterface Part {\n  readonly mimeType?: string;\n  readonly filename?: string;\n  readonly headers?: readonly { readonly name: string; readonly value: string }[];\n  readonly body?: { readonly data?: string; readonly size?: number; readonly attachmentId?: string };\n  readonly parts?: readonly Part[];\n}\ninterface Message {\n  readonly id: string;\n  readonly threadId: string;\n  readonly labelIds?: readonly string[];\n  readonly snippet?: string;\n  readonly internalDate?: string;\n  readonly payload?: Part;\n}\n\nconst header = (part: Part | undefined, name: string) =>\n  part?.headers?.find((h) => h.name.toLowerCase() === name.toLowerCase())?.value;\n\nconst charset = (part: Part) => /charset=\"?([^\";]+)\"?/i.exec(header(part, \"Content-Type\") ?? \"\")?.[1];\n\n/** The message text: its text/plain part, else its HTML part as text. Attachments are listed, not read. */\nconst content = (payload: Part | undefined) => {\n  let plain: string | undefined;\n  let html: string | undefined;\n  const attachments: { filename: string; mimeType: string; size: number; attachmentId: string }[] = [];\n  const walk = (part: Part) => {\n    if (part.filename && part.body?.attachmentId) {\n      attachments.push({\n        filename: part.filename,\n        mimeType: part.mimeType ?? \"application/octet-stream\",\n        size: part.body.size ?? 0,\n        attachmentId: part.body.attachmentId,\n      });\n      return;\n    }\n    if (part.body?.data && part.mimeType === \"text/plain\" && plain === undefined) plain = decodeBody(part.body.data, charset(part));\n    if (part.body?.data && part.mimeType === \"text/html\" && html === undefined) html = decodeBody(part.body.data, charset(part));\n    for (const child of part.parts ?? []) walk(child);\n  };\n  if (payload) walk(payload);\n  return { body: (plain ?? (html === undefined ? \"\" : htmlToText(html))).trim(), attachments };\n};\n\n/** Label IDs to names; system labels keep their IDs (INBOX, UNREAD, STARRED...). */\nconst labelNames = async (ctx: Base, target: Target) => {\n  const { labels = [] } = await google(ctx, target, `${base}/labels`);\n  return new Map<string, string>((labels as { id: string; name: string }[]).map((label) => [label.id, label.name]));\n};\n\nconst summary = (target: Target, message: Message, names: Map<string, string>) => ({\n  account: target.email,\n  messageId: message.id,\n  threadId: message.threadId,\n  from: header(message.payload, \"From\") ?? \"\",\n  to: header(message.payload, \"To\") ?? \"\",\n  subject: header(message.payload, \"Subject\") ?? \"\",\n  date: message.internalDate ? new Date(Number(message.internalDate)).toISOString() : \"\",\n  snippet: message.snippet ?? \"\",\n  unread: message.labelIds?.includes(\"UNREAD\") ?? false,\n  labels: (message.labelIds ?? []).filter((id) => id !== \"UNREAD\").map((id) => names.get(id) ?? id),\n});\n\nconst full = (target: Target, message: Message, names: Map<string, string>) => ({\n  ...summary(target, message, names),\n  cc: header(message.payload, \"Cc\") ?? \"\",\n  replyTo: header(message.payload, \"Reply-To\") ?? \"\",\n  ...content(message.payload),\n});\n\n/** Resolves label names or IDs, case-insensitively, to IDs. */\nconst labelIds = (names: Map<string, string>, wanted: readonly string[]) => {\n  const byName = new Map([...names].map(([id, name]) => [name.toLowerCase(), id]));\n  return wanted.map((label) => {\n    const id = names.has(label) ? label : byName.get(label.toLowerCase());\n    if (id === undefined) throw new Error(`No Gmail label named ${label}. Create it first, or list labels with gmail.labels.`);\n    return id;\n  });\n};\n\nconst Compose = {\n  account,\n  to: array(string()).optional(),\n  cc: array(string()).optional(),\n  bcc: array(string()).optional(),\n  subject: string().optional(),\n  body: string(),\n  html: boolean().optional(),\n  replyToMessageId: string().optional(),\n  replyAll: boolean().optional(),\n  from: string().optional(),\n};\ntype ComposeInput = {\n  readonly account?: string;\n  readonly to?: readonly string[];\n  readonly cc?: readonly string[];\n  readonly bcc?: readonly string[];\n  readonly subject?: string;\n  readonly body: string;\n  readonly html?: boolean;\n  readonly replyToMessageId?: string;\n  readonly replyAll?: boolean;\n  readonly from?: string;\n};\n\nconst addresses = (value: string | undefined) =>\n  (value ?? \"\")\n    .split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/)\n    .map((item) => item.trim())\n    .filter(Boolean);\nconst bare = (address: string) => (/<([^>]+)>/.exec(address)?.[1] ?? address).trim().toLowerCase();\n\n/**\n * Builds the RFC 2822 message. A reply takes the original's thread, subject and references, and\n * addresses its sender (and, with replyAll, everyone else on it except this account).\n */\nconst compose = async (ctx: Base, target: Target, input: ComposeInput) => {\n  let to = [...(input.to ?? [])];\n  let cc = [...(input.cc ?? [])];\n  let subject = input.subject;\n  let threadId: string | undefined;\n  const extra: string[] = [];\n  if (input.replyToMessageId) {\n    const original: Message = await google(ctx, target, `${base}/messages/${encodeURIComponent(input.replyToMessageId)}`, {\n      search: { format: \"metadata\", metadataHeaders: [\"From\", \"To\", \"Cc\", \"Subject\", \"Message-ID\", \"References\", \"Reply-To\"] },\n    });\n    threadId = original.threadId;\n    const messageId = header(original.payload, \"Message-ID\");\n    if (messageId) {\n      extra.push(`In-Reply-To: ${messageId}`);\n      extra.push(`References: ${[header(original.payload, \"References\"), messageId].filter(Boolean).join(\" \")}`);\n    }\n    const originalSubject = header(original.payload, \"Subject\") ?? \"\";\n    subject ??= /^re:/i.test(originalSubject) ? originalSubject : `Re: ${originalSubject}`;\n    const self = target.email.toLowerCase();\n    const sender = header(original.payload, \"Reply-To\") ?? header(original.payload, \"From\") ?? \"\";\n    // Replying to your own message goes back to its recipients.\n    const fromSelf = bare(header(original.payload, \"From\") ?? \"\") === self;\n    if (to.length === 0) to = fromSelf ? addresses(header(original.payload, \"To\")) : addresses(sender);\n    if (input.replyAll) {\n      const already = new Set([...to, ...cc].map(bare));\n      for (const address of [...addresses(header(original.payload, \"To\")), ...addresses(header(original.payload, \"Cc\"))]) {\n        if (bare(address) === self || already.has(bare(address))) continue;\n        already.add(bare(address));\n        cc.push(address);\n      }\n    }\n  }\n  const lines = [\n    ...(input.from ? [`From: ${input.from}`] : []),\n    ...(to.length ? [`To: ${to.join(\", \")}`] : []),\n    ...(cc.length ? [`Cc: ${cc.join(\", \")}`] : []),\n    ...(input.bcc?.length ? [`Bcc: ${input.bcc.join(\", \")}`] : []),\n    `Subject: ${encodeHeader(subject ?? \"\")}`,\n    ...extra,\n    \"MIME-Version: 1.0\",\n    `Content-Type: ${input.html ? \"text/html\" : \"text/plain\"}; charset=\"UTF-8\"`,\n    \"Content-Transfer-Encoding: base64\",\n    \"\",\n    base64Lines(input.body),\n  ];\n  return { raw: base64url(lines.join(\"\\r\\n\")), threadId, to, cc, subject: subject ?? \"\" };\n};\n\n/** Matching threads across targets, newest first, each summarised by its latest message. */\nexport const searchMail = async (ctx: Base, targets: readonly Target[], q: string, max: number) => {\n  const { items, errors } = await fanOut(targets, async (target) => {\n    const [{ threads = [] }, names] = await Promise.all([\n      google(ctx, target, `${base}/threads`, { search: { q, maxResults: max } }),\n      labelNames(ctx, target),\n    ]);\n    return mapLimit(threads as { id: string }[], 10, async ({ id }) => {\n      const thread: { messages?: Message[] } = await google(ctx, target, `${base}/threads/${id}`, {\n        search: { format: \"metadata\", metadataHeaders: [\"From\", \"To\", \"Subject\", \"Date\"] },\n      });\n      const messages = thread.messages ?? [];\n      const latest = messages.at(-1)!;\n      return {\n        ...summary(target, latest, names),\n        messageCount: messages.length,\n        unread: messages.some((message) => message.labelIds?.includes(\"UNREAD\")),\n      };\n    });\n  });\n  items.sort((a, b) => b.date.localeCompare(a.date));\n  return { threads: items.slice(0, max), errors };\n};\n\n/** The curated tools and their router's metadata; `source` names the package's accounts. */\nexport const gmail = (source: Source) => ({\n  tools: {\n    search: query(\n      {\n        description:\n          \"Search mail with Gmail search syntax (from:, to:, subject:, is:unread, has:attachment, newer_than:7d, label:, in:inbox...) across every linked Google account, or one. Returns matching threads, newest first, each with its latest message's sender, subject, date and snippet. Read one with readThread.\",\n        input: object({\n          query: string(),\n          account,\n          max: number().optional(),\n        }),\n      },\n      async (ctx: Context, input) =>\n        searchMail(ctx, await select(ctx, source, input.account), input.query, Math.min(Math.max(input.max ?? 20, 1), 100)),\n    ),\n    readThread: query(\n      {\n        description: \"Read a whole thread as decoded text: every message's headers, body and attachment list, oldest first.\",\n        input: object({ account, threadId: string({ minLength: 1 }) }),\n      },\n      async (ctx: Context, input) => {\n        const target = await single(ctx, source, input.account);\n        const [thread, names] = await Promise.all([\n          google(ctx, target, `${base}/threads/${encodeURIComponent(input.threadId)}`, { search: { format: \"full\" } }),\n          labelNames(ctx, target),\n        ]);\n        return { account: target.email, threadId: input.threadId, messages: ((thread.messages ?? []) as Message[]).map((m) => full(target, m, names)) };\n      },\n    ),\n    readMessage: query(\n      {\n        description: \"Read one message as decoded text: headers, body (HTML converted to text) and attachment list.\",\n        input: object({ account, messageId: string({ minLength: 1 }) }),\n      },\n      async (ctx: Context, input) => {\n        const target = await single(ctx, source, input.account);\n        const [message, names] = await Promise.all([\n          google(ctx, target, `${base}/messages/${encodeURIComponent(input.messageId)}`, { search: { format: \"full\" } }),\n          labelNames(ctx, target),\n        ]);\n        return full(target, message, names);\n      },\n    ),\n    labels: query(\n      {\n        description: \"List each account's labels with their unread and total counts.\",\n        input: object({ account }),\n      },\n      async (ctx: Context, input) =>\n        fanOut(await select(ctx, source, input.account), async (target) => {\n          const { labels = [] } = await google(ctx, target, `${base}/labels`);\n          return mapLimit(labels as { id: string; name: string; type: string }[], 10, async (label) => {\n            const detail = await google(ctx, target, `${base}/labels/${encodeURIComponent(label.id)}`);\n            return {\n              account: target.email,\n              id: label.id,\n              name: label.name,\n              type: label.type,\n              unreadThreads: detail.threadsUnread ?? 0,\n              threads: detail.threadsTotal ?? 0,\n            };\n          });\n        }).then(({ items, errors }) => ({ labels: items, errors })),\n    ),\n    send: mutation(\n      {\n        description:\n          \"Send an email. For a reply, pass replyToMessageId: it stays in the thread, gets a Re: subject and goes to the original sender unless `to` is given; replyAll also copies the other recipients. `from` must be one of the account's send-as aliases.\",\n        input: object(Compose),\n        approval: always(),\n      },\n      async (ctx: WriteContext, input) => {\n        const target = await single(ctx, source, input.account);\n        const message = await compose(ctx, target, input);\n        if (message.to.length === 0 && message.cc.length === 0 && !input.bcc?.length) throw new Error(\"Pass at least one recipient.\");\n        const sent = await google(ctx, target, `${base}/messages/send`, {\n          method: \"POST\",\n          body: { raw: message.raw, ...(message.threadId ? { threadId: message.threadId } : {}) },\n        });\n        return { account: target.email, messageId: sent.id, threadId: sent.threadId, to: message.to, cc: message.cc, subject: message.subject };\n      },\n    ),\n    draft: mutation(\n      {\n        description: \"Save a draft without sending it. Takes the same fields as send, and recipients may be left out.\",\n        input: object(Compose),\n        approval: always(),\n      },\n      async (ctx: WriteContext, input) => {\n        const target = await single(ctx, source, input.account);\n        const message = await compose(ctx, target, input);\n        const draft = await google(ctx, target, `${base}/drafts`, {\n          method: \"POST\",\n          body: { message: { raw: message.raw, ...(message.threadId ? { threadId: message.threadId } : {}) } },\n        });\n        return { account: target.email, draftId: draft.id, messageId: draft.message?.id, threadId: draft.message?.threadId };\n      },\n    ),\n    modify: mutation(\n      {\n        description:\n          \"Change threads: archive (leave the inbox), mark read or unread, star or unstar, move to trash, and add or remove labels by name. Applies to every message in each thread.\",\n        input: object({\n          account,\n          threadIds: array(string({ minLength: 1 })),\n          archive: boolean().optional(),\n          read: boolean().optional(),\n          starred: boolean().optional(),\n          trash: boolean().optional(),\n          addLabels: array(string()).optional(),\n          removeLabels: array(string()).optional(),\n        }),\n        approval: always(),\n      },\n      async (ctx: WriteContext, input) => {\n        const target = await single(ctx, source, input.account);\n        const names = await labelNames(ctx, target);\n        const add = labelIds(names, input.addLabels ?? []);\n        const remove = labelIds(names, input.removeLabels ?? []);\n        if (input.archive) remove.push(\"INBOX\");\n        if (input.read === true) remove.push(\"UNREAD\");\n        if (input.read === false) add.push(\"UNREAD\");\n        if (input.starred === true) add.push(\"STARRED\");\n        if (input.starred === false) remove.push(\"STARRED\");\n        await mapLimit(input.threadIds, 10, async (id) => {\n          const thread = encodeURIComponent(id);\n          if (input.trash) await google(ctx, target, `${base}/threads/${thread}/trash`, { method: \"POST\" });\n          if (add.length || remove.length)\n            await google(ctx, target, `${base}/threads/${thread}/modify`, {\n              method: \"POST\",\n              body: { addLabelIds: add, removeLabelIds: remove },\n            });\n        });\n        return { account: target.email, threads: input.threadIds.length, added: add, removed: remove, trashed: input.trash ?? false };\n      },\n    ),\n    attachment: query(\n      {\n        description:\n          \"Read an attachment listed by readMessage or readThread. Text attachments (text/*, JSON, CSV, XML) come back as text; others as base64.\",\n        input: object({ account, messageId: string({ minLength: 1 }), attachmentId: string({ minLength: 1 }), mimeType: string().optional() }),\n      },\n      async (ctx: Context, input) => {\n        const target = await single(ctx, source, input.account);\n        const { data = \"\", size } = await google(\n          ctx,\n          target,\n          `${base}/messages/${encodeURIComponent(input.messageId)}/attachments/${encodeURIComponent(input.attachmentId)}`,\n        );\n        const text = /^(text\\/|application\\/(json|xml|csv))/.test(input.mimeType ?? \"\");\n        return text ? { size, text: decodeBody(data) } : { size, base64: (data as string).replaceAll(\"-\", \"+\").replaceAll(\"_\", \"/\") };\n      },\n    ),\n  },\n  meta: {\n    title: \"Gmail\",\n    description: \"Search, read and send mail across every linked Google account.\",\n    instructions: `search spans every linked account unless \\`account\\` (an address) is given; its results carry the account, and reads and writes take that account. Writes need \\`account\\` only when several accounts are linked. The full Gmail API is under ${source.api(\"gmail\")}.`,\n  },\n});\n"},{"path":"tools/people.ts","content":"// Generated by scripts/google-vendor.ts from shared/google-tools; edit the original and rerun it.\n// Contacts tools shaped for agents: one search across saved contacts, people you have emailed and\n// the Workspace directory, for every linked account.\nimport { number, object, query, string } from \"apps\";\nimport { defined, fanOut, google, select, type Base, type Context, type Source, type Target } from \"./shared.js\";\n\nconst base = \"https://people.googleapis.com/v1\";\nconst mask = \"names,emailAddresses,phoneNumbers,organizations\";\n\nconst person = (target: Target, source: string, item: any) =>\n  defined({\n    account: target.email,\n    source,\n    resourceName: item.resourceName as string,\n    name: (item.names?.[0]?.displayName ?? \"\") as string,\n    emails: ((item.emailAddresses ?? []) as { value: string }[]).map((e) => e.value),\n    phones: ((item.phoneNumbers ?? []) as { value: string }[]).map((p) => p.value),\n    organization: [item.organizations?.[0]?.title, item.organizations?.[0]?.name].filter(Boolean).join(\", \") || undefined,\n  });\n\n/** Saved contacts, other contacts and (on Workspace accounts) the directory, for one account. */\nexport const findPeople = async (ctx: Base, target: Target, text: string, max: number) => {\n  // Google asks for an empty warm-up search before the first real one; without it results can be empty.\n  await Promise.all([\n    google(ctx, target, `${base}/people:searchContacts`, { search: { query: \"\", readMask: \"names\" } }),\n    google(ctx, target, `${base}/otherContacts:search`, { search: { query: \"\", readMask: \"names\" } }),\n  ]);\n  const [saved, other, directory] = await Promise.allSettled([\n    google(ctx, target, `${base}/people:searchContacts`, { search: { query: text, readMask: mask, pageSize: max } }),\n    google(ctx, target, `${base}/otherContacts:search`, { search: { query: text, readMask: \"names,emailAddresses,phoneNumbers\", pageSize: max } }),\n    google(ctx, target, `${base}/people:searchDirectoryPeople`, {\n      search: { query: text, readMask: mask, pageSize: max, sources: \"DIRECTORY_SOURCE_TYPE_DOMAIN_PROFILE\" },\n    }),\n  ]);\n  if (saved.status === \"rejected\") throw saved.reason;\n  const found = [\n    ...((saved.value.results ?? []) as { person: unknown }[]).map((r) => person(target, \"contacts\", r.person)),\n    ...(other.status === \"fulfilled\" ? ((other.value.results ?? []) as { person: unknown }[]).map((r) => person(target, \"other\", r.person)) : []),\n    // Consumer accounts have no directory; that search fails and is left out.\n    ...(directory.status === \"fulfilled\" ? ((directory.value.people ?? []) as unknown[]).map((p) => person(target, \"directory\", p)) : []),\n  ];\n  const seen = new Set<string>();\n  return found\n    .filter((p) => {\n      const key = p.emails[0]?.toLowerCase() ?? p.resourceName;\n      if (seen.has(key)) return false;\n      seen.add(key);\n      return true;\n    })\n    .slice(0, max);\n};\n\n/** The curated tools and their router's metadata; `source` names the package's accounts. */\nexport const contacts = (source: Source) => ({\n  tools: {\n    search: query(\n      {\n        description:\n          \"Find people by name, email or phone across every linked Google account (or one): saved contacts, people you have emailed (other contacts) and the Workspace directory. Use it to turn a name into an email address.\",\n        input: object({ query: string({ minLength: 1 }), account: string().optional(), max: number().optional() }),\n      },\n      async (ctx: Context, input) => {\n        const max = Math.min(Math.max(input.max ?? 10, 1), 30);\n        const { items, errors } = await fanOut(await select(ctx, source, input.account), (target) => findPeople(ctx, target, input.query, max));\n        return { people: items, errors };\n      },\n    ),\n  },\n  meta: {\n    title: \"Google Contacts\",\n    description: \"Find people across every linked Google account.\",\n    instructions: `Contact edits and groups are under ${source.api(\"contacts\")}.`,\n  },\n});\n"},{"path":"tools/shared.ts","content":"// Generated by scripts/google-vendor.ts from shared/google-tools; edit the original and rerun it.\n// Helpers for the curated tools: choosing accounts, calling Google with one of them, running a read\n// across every linked account, and the encodings Gmail and Calendar need.\nimport { decodeJson, json, object, string, type MutationContext, type QueryContext } from \"apps\";\n\nexport type Context = QueryContext;\nexport type WriteContext = MutationContext;\n/** What the helpers use of a query or mutation context. */\nexport type Base = Pick<Context, \"fetch\" | \"signal\" | \"cache\">;\n/** A linked Google account, as any of the Google packages' slots provides it. */\nexport interface Account {\n  readonly id: string;\n  readonly fields: { readonly access_token: string };\n}\n\n/** How a package reads an account's address with the scopes it already has. */\nexport type Address = (load: { readonly fetch: typeof fetch; readonly signal: AbortSignal }, account: Account) => Promise<string>;\n\n/** The accounts a package's curated tools run with, and how it names them. */\nexport interface Source {\n  readonly accounts: readonly Account[];\n  readonly address: Address;\n  /** Where the package mounts a product's complete API (`gmail` → `api.gmail`), named in the tools' instructions. */\n  readonly api: (product: string) => string;\n}\n\nconst read =\n  <T>(url: string, schema: Parameters<typeof decodeJson<T>>[1], pick: (body: T) => string): Address =>\n  async ({ fetch, signal }, account) =>\n    pick(await decodeJson(await fetch(url, { signal, headers: { Authorization: `Bearer ${account.fields.access_token}` } }), schema));\n\n/** Address lookups for each package's scopes. */\nexport const addresses = {\n  /** Needs the `email` scope; `url` is the userinfo endpoint on a host the provider allows. */\n  userinfo: (url: string) => read(url, object({ email: string() }), (body) => body.email),\n  gmail: read(\"https://gmail.googleapis.com/gmail/v1/users/me/profile\", object({ emailAddress: string() }), (body) => body.emailAddress),\n  /** The primary calendar's ID is the account's address. */\n  calendar: read(\"https://www.googleapis.com/calendar/v3/calendars/primary\", object({ id: string() }), (body) => body.id),\n  drive: read(\n    \"https://www.googleapis.com/drive/v3/about?fields=user(emailAddress)\",\n    object({ user: object({ emailAddress: string() }) }),\n    (body) => body.user.emailAddress,\n  ),\n  /** For scopes that reveal no address, such as Tasks': accounts are named by their ID. */\n  id: (async (_load, account) => account.id) as Address,\n};\n\n/** One linked account with the address it signs in as. */\nexport interface Target {\n  readonly account: Account;\n  readonly email: string;\n}\n\n/** The account's address, cached per account so a fan-out costs one request per account at most once a day. */\nconst emailOf = (ctx: Base, source: Source, account: Account) =>\n  ctx.cache.forAccount(account).get({\n    key: \"email\",\n    schema: string(),\n    freshFor: \"1 day\",\n    load: (load) => source.address(load, account),\n  });\n\n/** Every linked account with its address. */\nexport const linked = (ctx: Base, source: Source): Promise<Target[]> =>\n  Promise.all(source.accounts.map(async (account) => ({ account, email: await emailOf(ctx, source, account) })));\n\n/** The accounts a call names: one by address or account ID, or all of them when `account` is omitted. */\nexport const select = async (ctx: Base, source: Source, account: string | undefined): Promise<Target[]> => {\n  const all = await linked(ctx, source);\n  if (all.length === 0) throw new Error(\"No Google account is linked to this app. Connect one first.\");\n  if (account === undefined) return all;\n  const wanted = account.trim().toLowerCase();\n  const match = all.filter((target) => target.email.toLowerCase() === wanted || target.account.id === account);\n  if (match.length === 0)\n    throw new Error(`No linked Google account matches ${account}. Linked accounts: ${all.map((t) => t.email).join(\", \")}.`);\n  return match;\n};\n\n/** The one account a write uses: the named one, or the only linked account. */\nexport const single = async (ctx: Base, source: Source, account: string | undefined): Promise<Target> => {\n  const targets = await select(ctx, source, account);\n  if (targets.length > 1)\n    throw new Error(`Several Google accounts are linked; pass account as one of: ${targets.map((t) => t.email).join(\", \")}.`);\n  return targets[0]!;\n};\n\n/**\n * Runs a read on each target at once. One account's failure does not hide the others' results: it\n * is reported under `errors` with the account's address.\n */\nexport const fanOut = async <T>(\n  targets: readonly Target[],\n  run: (target: Target) => Promise<readonly T[]>,\n): Promise<{ readonly items: T[]; readonly errors: { readonly account: string; readonly message: string }[] }> => {\n  const settled = await Promise.allSettled(targets.map(run));\n  const items: T[] = [];\n  const errors: { account: string; message: string }[] = [];\n  settled.forEach((result, index) => {\n    if (result.status === \"fulfilled\") items.push(...result.value);\n    else errors.push({ account: targets[index]!.email, message: result.reason instanceof Error ? result.reason.message : String(result.reason) });\n  });\n  return { items, errors };\n};\n\n/** Drops undefined fields, which tool results cannot carry: results must be plain JSON. */\nexport const defined = <T extends object>(value: T): T =>\n  Object.fromEntries(Object.entries(value).filter(([, field]) => field !== undefined)) as T;\n\n/** Calls a Google JSON API with the target's token. `search` values left undefined are omitted. */\nexport const google = async (\n  ctx: Base,\n  target: Target,\n  url: string,\n  init: {\n    readonly method?: string;\n    readonly body?: unknown;\n    readonly search?: Readonly<Record<string, string | number | boolean | readonly string[] | undefined>>;\n  } = {},\n): Promise<any> => {\n  const address = new URL(url);\n  for (const [key, value] of Object.entries(init.search ?? {})) {\n    if (value === undefined) continue;\n    for (const item of Array.isArray(value) ? value : [value]) address.searchParams.append(key, String(item));\n  }\n  const response = await ctx.fetch(address.toString(), {\n    method: init.method ?? \"GET\",\n    signal: ctx.signal,\n    headers: {\n      Authorization: `Bearer ${target.account.fields.access_token}`,\n      ...(init.body === undefined ? {} : { \"content-type\": \"application/json\" }),\n    },\n    body: init.body === undefined ? undefined : JSON.stringify(init.body),\n  });\n  if (response.status === 204) return {};\n  return decodeJson(response, json());\n};\n\n/** Fetches a body as text, for exports and downloads. */\nexport const googleText = async (ctx: Base, target: Target, url: string): Promise<string> => {\n  const response = await ctx.fetch(url, {\n    signal: ctx.signal,\n    headers: { Authorization: `Bearer ${target.account.fields.access_token}` },\n  });\n  if (!response.ok) throw new Error(`Google answered ${response.status}: ${(await response.text()).slice(0, 500)}`);\n  return response.text();\n};\n\n/** Bounded parallelism, so a 50-thread search does not open 50 connections at once. */\nexport const mapLimit = async <T, R>(items: readonly T[], limit: number, run: (item: T) => Promise<R>): Promise<R[]> => {\n  const results: R[] = new Array(items.length);\n  let next = 0;\n  const worker = async () => {\n    while (next < items.length) {\n      const index = next++;\n      results[index] = await run(items[index]!);\n    }\n  };\n  await Promise.all(Array.from({ length: Math.min(limit, items.length) }, worker));\n  return results;\n};\n\nconst bytesToBinary = (bytes: Uint8Array) => {\n  let binary = \"\";\n  for (let i = 0; i < bytes.length; i += 0x8000) binary += String.fromCharCode(...bytes.subarray(i, i + 0x8000));\n  return binary;\n};\n\n/** UTF-8 text as base64url, the encoding Gmail's `raw` field takes. */\nexport const base64url = (text: string) =>\n  btoa(bytesToBinary(new TextEncoder().encode(text))).replaceAll(\"+\", \"-\").replaceAll(\"/\", \"_\").replace(/=+$/, \"\");\n\n/** Base64 for a MIME body, wrapped at 76 characters. */\nexport const base64Lines = (text: string) => btoa(bytesToBinary(new TextEncoder().encode(text))).replace(/.{76}/g, \"$&\\r\\n\");\n\n/** Decodes a Gmail body part (base64url bytes) in the part's charset. */\nexport const decodeBody = (data: string, charset = \"utf-8\") => {\n  const binary = atob(data.replaceAll(\"-\", \"+\").replaceAll(\"_\", \"/\"));\n  const bytes = Uint8Array.from(binary, (char) => char.charCodeAt(0));\n  try {\n    return new TextDecoder(charset).decode(bytes);\n  } catch {\n    return new TextDecoder(\"utf-8\").decode(bytes);\n  }\n};\n\nconst entities: Record<string, string> = { amp: \"&\", lt: \"<\", gt: \">\", quot: '\"', apos: \"'\", nbsp: \" \" };\n\n/** Readable text from an HTML body: block elements become line breaks, tags and scripts go. */\nexport const htmlToText = (html: string) =>\n  html\n    .replace(/<(script|style|head)[\\s\\S]*?<\\/\\1>/gi, \"\")\n    .replace(/<br\\s*\\/?>/gi, \"\\n\")\n    .replace(/<\\/(p|div|tr|li|h[1-6]|blockquote)>/gi, \"\\n\")\n    .replace(/<li[^>]*>/gi, \"- \")\n    .replace(/<a\\s[^>]*href=\"([^\"]*)\"[^>]*>([\\s\\S]*?)<\\/a>/gi, (_, href: string, text: string) =>\n      text.trim() && !href.startsWith(\"mailto:\") && text.trim() !== href ? `${text} (${href})` : text,\n    )\n    .replace(/<[^>]+>/g, \"\")\n    .replace(/&(#x?[0-9a-f]+|\\w+);/gi, (match, code: string) => {\n      if (code.startsWith(\"#x\") || code.startsWith(\"#X\")) return String.fromCodePoint(parseInt(code.slice(2), 16));\n      if (code.startsWith(\"#\")) return String.fromCodePoint(parseInt(code.slice(1), 10));\n      return entities[code.toLowerCase()] ?? match;\n    })\n    .replace(/[ \\t]+\\n/g, \"\\n\")\n    .replace(/\\n{3,}/g, \"\\n\\n\")\n    .trim();\n\n/** A header value with non-ASCII text as an RFC 2047 encoded word. */\nexport const encodeHeader = (value: string) =>\n  /^[\\x20-\\x7e]*$/.test(value) ? value : `=?UTF-8?B?${btoa(bytesToBinary(new TextEncoder().encode(value)))}?=`;\n\n/** Milliseconds a zone is ahead of UTC at an instant. */\nconst zoneOffset = (zone: string, instant: number) => {\n  const parts = Object.fromEntries(\n    new Intl.DateTimeFormat(\"en-US\", {\n      timeZone: zone,\n      hourCycle: \"h23\",\n      year: \"numeric\",\n      month: \"2-digit\",\n      day: \"2-digit\",\n      hour: \"2-digit\",\n      minute: \"2-digit\",\n      second: \"2-digit\",\n    })\n      .formatToParts(new Date(instant))\n      .map((part) => [part.type, part.value]),\n  );\n  const asUtc = Date.UTC(+parts.year!, +parts.month! - 1, +parts.day!, +parts.hour!, +parts.minute!, +parts.second!);\n  return asUtc - Math.floor(instant / 1000) * 1000;\n};\n\n/** The instant a wall-clock time in a zone names. */\nexport const zonedTime = (zone: string, year: number, month: number, day: number, hour = 0, minute = 0) => {\n  const guess = Date.UTC(year, month - 1, day, hour, minute);\n  const first = guess - zoneOffset(zone, guess);\n  return first - (zoneOffset(zone, first) - zoneOffset(zone, guess));\n};\n\n/** The calendar date (year, month, day) of an instant in a zone. */\nexport const zonedDate = (zone: string, instant: number) => {\n  const [year, month, day] = new Intl.DateTimeFormat(\"en-CA\", { timeZone: zone, year: \"numeric\", month: \"2-digit\", day: \"2-digit\" })\n    .format(new Date(instant))\n    .split(\"-\")\n    .map(Number) as [number, number, number];\n  return { year, month, day };\n};\n\n/**\n * An instant from what a model is likely to pass: an RFC 3339 time, a date (midnight in `zone`),\n * \"now\", \"today\", \"tomorrow\" or \"yesterday\".\n */\nexport const parseTime = (value: string, zone: string, now = Date.now()) => {\n  const text = value.trim().toLowerCase();\n  if (text === \"now\") return now;\n  const shift = { yesterday: -1, today: 0, tomorrow: 1 }[text];\n  if (shift !== undefined) {\n    const today = zonedDate(zone, now);\n    return zonedTime(zone, today.year, today.month, today.day + shift);\n  }\n  const date = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(text);\n  if (date) return zonedTime(zone, +date[1]!, +date[2]!, +date[3]!);\n  const local = /^(\\d{4})-(\\d{2})-(\\d{2})t(\\d{2}):(\\d{2})(?::\\d{2}(?:\\.\\d+)?)?$/.exec(text);\n  if (local) return zonedTime(zone, +local[1]!, +local[2]!, +local[3]!, +local[4]!, +local[5]!);\n  const instant = Date.parse(value);\n  if (Number.isNaN(instant))\n    throw new Error(`Could not read the time \"${value}\". Use RFC 3339 (2026-10-14T09:00:00-07:00), a date (2026-10-14), \"now\", \"today\" or \"tomorrow\".`);\n  return instant;\n};\n\nconst TimeZone = object({ value: string() });\n\n/** The zone of the account's Calendar settings, which dates without an offset are read in. */\nexport const calendarZone = async (ctx: Base, target: Target) =>\n  ctx.cache.forAccount(target.account).get({\n    key: \"calendar-zone\",\n    schema: string(),\n    freshFor: \"1 day\",\n    load: async ({ fetch, signal }) => {\n      const response = await fetch(\"https://www.googleapis.com/calendar/v3/users/me/settings/timezone\", {\n        signal,\n        headers: { Authorization: `Bearer ${target.account.fields.access_token}` },\n      });\n      return (await decodeJson(response, TimeZone)).value;\n    },\n  });\n"},{"path":"tools/sheets.ts","content":"// Generated by scripts/google-vendor.ts from shared/google-tools; edit the original and rerun it.\n// Sheets tools shaped for agents: read a range (or a whole tab) as rows, and append or write rows,\n// without A1 bookkeeping for the common case.\nimport { array, json, mutation, object, query, string } from \"apps\";\nimport { always } from \"apps/operations/approval\";\nimport { google, single, type Base, type Context, type Source, type Target, type WriteContext } from \"./shared.js\";\n\nconst base = \"https://sheets.googleapis.com/v4/spreadsheets\";\nconst account = string().optional();\nconst spreadsheetId = string({ minLength: 1 });\n\nconst tabs = async (ctx: Base, target: Target, id: string) => {\n  const meta = await google(ctx, target, `${base}/${encodeURIComponent(id)}`, {\n    search: { fields: \"properties.title,sheets.properties(sheetId,title,gridProperties(rowCount,columnCount))\" },\n  });\n  return {\n    title: meta.properties?.title as string,\n    tabs: ((meta.sheets ?? []) as any[]).map((sheet) => ({\n      title: sheet.properties.title as string,\n      rows: sheet.properties.gridProperties?.rowCount as number,\n      columns: sheet.properties.gridProperties?.columnCount as number,\n    })),\n  };\n};\n\n/** A tab name alone is a valid A1 range; quote it so spaces and punctuation survive. */\nconst tabRange = (title: string) => `'${title.replaceAll(\"'\", \"''\")}'`;\n\n/** The curated tools and their router's metadata; `source` names the package's accounts. */\nexport const sheets = (source: Source) => ({\n  tools: {\n    read: query(\n      {\n        description:\n          \"Read a spreadsheet: its tabs, and the values of `range` (A1 notation such as Sheet1!A1:D20, or just a tab name). Without a range, reads the first tab. Values are formatted as shown in Sheets.\",\n        input: object({ account, spreadsheetId, range: string().optional() }),\n      },\n      async (ctx: Context, input) => {\n        const target = await single(ctx, source, input.account);\n        const info = await tabs(ctx, target, input.spreadsheetId);\n        const range = input.range ?? (info.tabs[0] ? tabRange(info.tabs[0].title) : \"A1:Z1000\");\n        const values = await google(ctx, target, `${base}/${encodeURIComponent(input.spreadsheetId)}/values/${encodeURIComponent(range)}`);\n        return { account: target.email, ...info, range: values.range as string, rows: (values.values ?? []) as unknown[][] };\n      },\n    ),\n    append: mutation(\n      {\n        description:\n          \"Append rows after the last row of a table: `range` is a tab name or the table's range. Each row is an array of cell values; strings starting with = are formulas.\",\n        input: object({ account, spreadsheetId, range: string({ minLength: 1 }), rows: array(array(json())) }),\n        approval: always(),\n      },\n      async (ctx: WriteContext, input) => {\n        const target = await single(ctx, source, input.account);\n        const result = await google(ctx, target, `${base}/${encodeURIComponent(input.spreadsheetId)}/values/${encodeURIComponent(input.range)}:append`, {\n          method: \"POST\",\n          search: { valueInputOption: \"USER_ENTERED\", insertDataOption: \"INSERT_ROWS\" },\n          body: { values: input.rows },\n        });\n        return { account: target.email, updatedRange: result.updates?.updatedRange, updatedRows: result.updates?.updatedRows };\n      },\n    ),\n    write: mutation(\n      {\n        description: \"Overwrite the cells of `range` (A1 notation, starting cell is enough) with rows of values; strings starting with = are formulas.\",\n        input: object({ account, spreadsheetId, range: string({ minLength: 1 }), rows: array(array(json())) }),\n        approval: always(),\n      },\n      async (ctx: WriteContext, input) => {\n        const target = await single(ctx, source, input.account);\n        const result = await google(ctx, target, `${base}/${encodeURIComponent(input.spreadsheetId)}/values/${encodeURIComponent(input.range)}`, {\n          method: \"PUT\",\n          search: { valueInputOption: \"USER_ENTERED\" },\n          body: { values: input.rows },\n        });\n        return { account: target.email, updatedRange: result.updatedRange, updatedCells: result.updatedCells };\n      },\n    ),\n  },\n  meta: {\n    title: \"Google Sheets\",\n    description: \"Read and add rows to spreadsheets.\",\n    instructions: `The spreadsheet ID is the long part of its URL; Drive search finds spreadsheets by name. Formatting, charts and batch updates are under ${source.api(\"sheets\")}.`,\n  },\n});\n"},{"path":"tools/tasks.ts","content":"// Generated by scripts/google-vendor.ts from shared/google-tools; edit the original and rerun it.\n// Tasks tools shaped for agents: open tasks from every list of every linked account, and adding\n// or completing one by plain fields.\nimport { boolean, mutation, object, query, string } from \"apps\";\nimport { always } from \"apps/operations/approval\";\nimport { defined, fanOut, google, select, single, type Context, type Source, type WriteContext } from \"./shared.js\";\n\nconst base = \"https://tasks.googleapis.com/tasks/v1\";\nconst account = string().optional();\n\n/** The curated tools and their router's metadata; `source` names the package's accounts. */\nexport const tasks = (source: Source) => ({\n  tools: {\n    list: query(\n      {\n        description:\n          \"List tasks from every task list of every linked Google account (or one), open tasks only unless includeCompleted. Tasks with a due date come first, soonest first.\",\n        input: object({ account, includeCompleted: boolean().optional(), dueBefore: string().optional() }),\n      },\n      async (ctx: Context, input) => {\n        const { items, errors } = await fanOut(await select(ctx, source, input.account), async (target) => {\n          const { items: lists = [] } = await google(ctx, target, `${base}/users/@me/lists`, { search: { maxResults: 100 } });\n          const perList = await Promise.all(\n            (lists as { id: string; title: string }[]).map(async (list) => {\n              const { items = [] } = await google(ctx, target, `${base}/lists/${encodeURIComponent(list.id)}/tasks`, {\n                search: {\n                  maxResults: 100,\n                  showCompleted: input.includeCompleted ?? false,\n                  showHidden: input.includeCompleted ?? false,\n                  dueMax: input.dueBefore ? new Date(input.dueBefore).toISOString() : undefined,\n                },\n              });\n              return (items as any[]).map((task) =>\n                defined({\n                account: target.email,\n                listId: list.id,\n                list: list.title,\n                taskId: task.id as string,\n                title: task.title as string,\n                notes: task.notes as string | undefined,\n                // Google stores only the date of a due time.\n                due: (task.due as string | undefined)?.slice(0, 10),\n                status: task.status as string,\n                parent: task.parent as string | undefined,\n                }),\n              );\n            }),\n          );\n          return perList.flat();\n        });\n        items.sort((a, b) => (a.due ?? \"9999\").localeCompare(b.due ?? \"9999\"));\n        return { tasks: items, errors };\n      },\n    ),\n    add: mutation(\n      {\n        description: \"Add a task. listId defaults to the account's default list; due is a date (2026-10-14).\",\n        input: object({ account, listId: string().optional(), title: string({ minLength: 1 }), notes: string().optional(), due: string().optional() }),\n        approval: always(),\n      },\n      async (ctx: WriteContext, input) => {\n        const target = await single(ctx, source, input.account);\n        const task = await google(ctx, target, `${base}/lists/${encodeURIComponent(input.listId ?? \"@default\")}/tasks`, {\n          method: \"POST\",\n          body: { title: input.title, notes: input.notes, due: input.due ? `${input.due.slice(0, 10)}T00:00:00.000Z` : undefined },\n        });\n        return defined({ account: target.email, taskId: task.id, title: task.title, due: task.due?.slice(0, 10) });\n      },\n    ),\n    complete: mutation(\n      {\n        description: \"Mark a task done, or open again with done set to false.\",\n        input: object({ account, listId: string({ minLength: 1 }), taskId: string({ minLength: 1 }), done: boolean().optional() }),\n        approval: always(),\n      },\n      async (ctx: WriteContext, input) => {\n        const target = await single(ctx, source, input.account);\n        const done = input.done ?? true;\n        const task = await google(ctx, target, `${base}/lists/${encodeURIComponent(input.listId)}/tasks/${encodeURIComponent(input.taskId)}`, {\n          method: \"PATCH\",\n          body: done ? { status: \"completed\" } : { status: \"needsAction\", completed: null },\n        });\n        return { account: target.email, taskId: task.id, title: task.title, status: task.status };\n      },\n    ),\n  },\n  meta: {\n    title: \"Google Tasks\",\n    description: \"Tasks across every linked Google account.\",\n    instructions: `List management and moving tasks are under ${source.api(\"tasks\")}.`,\n  },\n});\n"}]}