Scopes
Every endpoint declares a required scope. The bearer token must hold that
scope or the request fails with 403 insufficient_scope and a
WWW-Authenticate: Bearer error="insufficient_scope" scope="<scope>" header.
Scopes are granted when:
- the user approves the OAuth consent screen for a third-party client,
- the admin selects scopes when minting a PAT, or
- the user connects an AI assistant, and the
MCP consent screen grants the two
mcp:scheduling:*aliases below.
Active scopes
| Scope | What it grants |
|---|---|
user:read | Read the authenticated user's profile (/v1/me). |
users:read | List and search organization members. (MCP only.) |
event_types:read | List and read event types. |
event_types:create | Create event types. (Reserved; no public write endpoints yet.) |
event_types:update | Modify event types. (MCP only.) |
event_types:delete | Delete event types. (Reserved.) |
slots:read | Check slot availability. |
bookings:read | List and read bookings. |
bookings:create | Create bookings. |
bookings:cancel | Cancel bookings. |
bookings:reschedule | Reschedule bookings. |
bookings:update | Patch booking metadata, responses, and attendee name. |
webhooks:read | List and read webhook subscriptions, and their recent deliveries (/v1/webhooks). |
webhooks:write | Create, edit, delete, rotate the secret of, and test webhooks. |
availability:read | Read schedules. (MCP only.) |
availability:write | Modify schedules. (MCP only.) |
meetings:read | Read the host-side meetings view. (MCP only.) |
meetings:write | Mark meetings as no-show. (MCP only.) |
series:read | List and read recurring meeting series. |
series:write | Create recurring series, and pause, resume, end, edit, or change their host. |
contacts:read | Search contacts and read meeting history. (MCP only.) |
single_use_links:read | List secret links. (MCP only.) |
single_use_links:write | Generate and delete secret links. (MCP only.) |
roundtables:read | List and read roundtables (group scheduling polls). (MCP only.) |
roundtables:write | Create and publish roundtables. (MCP only.) |
"Reserved" scopes are recognized by the auth server but nothing consumes them
yet, but they exist so apps can request the right surface ahead of the endpoints
landing. "MCP only" scopes are consumed by the
MCP server's tools (the
/mcp endpoint for AI assistants); no /v1/*
REST endpoint reads them yet.
Alias scopes
Some commonly-bundled scopes are exposed as aliases. When a token is granted with an alias, the alias is expanded at grant time into its constituent granular scopes, and runtime checks always read the expanded set.
| Alias | Expands to |
|---|---|
event_types:write | event_types:create, event_types:update, event_types:delete |
bookings:write | bookings:create, bookings:cancel, bookings:reschedule, bookings:update |
mcp:scheduling:read | user:read, event_types:read, slots:read, bookings:read, meetings:read, contacts:read, availability:read, single_use_links:read, roundtables:read, users:read |
mcp:scheduling:write | everything in mcp:scheduling:read, plus event_types:update, bookings:create, bookings:cancel, bookings:reschedule, meetings:write, availability:write, single_use_links:write, roundtables:write |
The two mcp:scheduling:* aliases are what the
AI-assistant consent screen
grants. They are OAuth-only: they never appear in the PAT scope picker, and
are only valid for tokens addressed to the MCP endpoint.
Practical consequence: a token granted bookings:write carries four granular
scopes, and that's the set you'll see in meta.request_id audit logs, in the
/v1/_ping response, and in the scope claim of an issued OAuth token.
Reserved scopes (not yet active)
These appear in discovery but no endpoint currently consumes them:
routing_forms:read routing_forms:create routing_forms:update
routing_forms:delete routing_forms:write teams:read
teams:write calendars:read calendars:write
analytics:read
Required scope per endpoint
| Method · Path | Scope |
|---|---|
GET /v1/_ping | none (auth only) |
GET /v1/me | user:read |
GET /v1/event-types | event_types:read |
GET /v1/event-types/:idOrSlug | event_types:read |
GET /v1/slots | slots:read |
GET /v1/slots/check | slots:read |
GET /v1/bookings | bookings:read |
GET /v1/bookings/:uid | bookings:read |
POST /v1/bookings | bookings:create |
POST /v1/bookings/:uid/cancel | bookings:cancel |
POST /v1/bookings/:uid/reschedule | bookings:reschedule |
PATCH /v1/bookings/:uid | bookings:update |
GET /v1/webhooks | webhooks:read |
GET /v1/webhooks/:id | webhooks:read |
GET /v1/webhooks/:id/deliveries | webhooks:read |
POST /v1/webhooks | webhooks:write |
PATCH /v1/webhooks/:id | webhooks:write |
DELETE /v1/webhooks/:id | webhooks:write |
POST /v1/webhooks/:id/rotate-secret | webhooks:write |
POST /v1/webhooks/:id/test | webhooks:write |
Requesting scopes
OAuth: include them on /v1/oauth/authorize as a space-separated scope
parameter. The set must be a subset of the client's registered allowed_scopes,
otherwise 400 invalid_scope. The user can narrow further from the consent
screen; granted scopes are the user's choice intersected with the request.
PAT: select scopes in the New API key dialog in Admin Center → API. Expanding the scope set on an existing key requires re-confirming your account password; narrowing does not.
Insufficient scope
{
"error": {
"code": "insufficient_scope",
"message": "This action requires the 'bookings:create' scope",
"details": { "required_scope": "bookings:create" },
"request_id": "req_…"
}
}
The remedy is always: mint or re-authorize a token that holds the required scope. Scopes cannot be elevated mid-session.
Last updated September 21, 2026.