Summary and recommendation
Calendly's REST API authenticates via OAuth 2.0 (authorization code flow) or a Personal Access Token passed as a Bearer token. There is no direct endpoint to list all users - enumeration requires GET /organization_memberships?organization=<org_uri>, using the organization URI retrieved from GET /users/me.
Rate limits are 60 requests/minute on Free, Standard, and Teams plans and 120 requests/minute on Enterprise; HTTP 429 responses include a Retry-After header that must be honored. Pagination is cursor-based with a default page size of 20 and a maximum of 100, controlled via the page_token parameter.
All resource identifiers in request bodies are full URIs, not bare UUIDs - passing a bare UUID will fail silently or return a 404.
API quick reference
| Has user API | Yes |
| Auth method | OAuth 2.0 (authorization code flow) or Personal Access Token (Bearer token) |
| Base URL | Official docs |
| SCIM available | Yes |
| SCIM plan required | Enterprise (minimum ~$15,000/year, 30+ users); SSO must be configured first. |
Authentication
Auth method: OAuth 2.0 (authorization code flow) or Personal Access Token (Bearer token)
Setup steps
- Register an OAuth application at https://developer.calendly.com to obtain a client_id and client_secret.
- Redirect users to https://auth.calendly.com/oauth/authorize with response_type=code, client_id, redirect_uri, and scope.
- Exchange the returned authorization code for an access_token and refresh_token via POST https://auth.calendly.com/oauth/token.
- Alternatively, generate a Personal Access Token (PAT) in Calendly account settings under Integrations > API & Webhooks.
- Include the token in all API requests as: Authorization: Bearer
.
Required scopes
| Scope | Description | Required for |
|---|---|---|
| default | Read access to the authenticated user's profile, event types, and scheduled events. | Most read operations including Get Current User and List Event Types. |
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| uri | string | Unique resource URI for the user (e.g. https://api.calendly.com/users/AAAAAAAAAAAAAAAA) | system-generated | immutable | Used as the user identifier in all API calls. |
| name | string | Full display name of the user. | required | editable via Calendly UI only | Not writable via REST API. |
| slug | string | URL slug used in the user's scheduling link. | system-generated | read-only via API | |
| string | Primary email address of the user. | required | read-only via API | Writable via SCIM. | |
| scheduling_url | string | Public scheduling page URL. | system-generated | read-only | |
| timezone | string | User's configured timezone (IANA format). | optional | read-only via API | |
| avatar_url | string|null | URL of the user's profile avatar. | optional | read-only via API | |
| created_at | datetime (ISO 8601) | Timestamp when the user account was created. | system-generated | immutable | |
| updated_at | datetime (ISO 8601) | Timestamp of last profile update. | system-generated | system-managed | |
| current_organization | string (URI) | URI of the organization the user belongs to. | system-generated | read-only | Used to scope organization-level queries. |
| role | string | User's role within the organization (e.g. owner, admin, user). | system-assigned | writable via Organization Membership endpoint | Values: owner, admin, user. |
| resource_type | string | Always 'User' for user objects. | system-generated | immutable |
Core endpoints
Get Current User
- Method: GET
- URL:
https://api.calendly.com/users/me - Watch out for: Returns only the authenticated user. There is no REST endpoint to list all users; use List Organization Memberships instead.
Request example
GET /users/me
Authorization: Bearer <token>
Response example
{
"resource": {
"uri": "https://api.calendly.com/users/AAAA",
"name": "Jane Doe",
"email": "jane@example.com",
"slug": "janedoe",
"timezone": "America/New_York",
"current_organization": "https://api.calendly.com/organizations/BBBB"
}
}
Get User by URI
- Method: GET
- URL:
https://api.calendly.com/users/{uuid} - Watch out for: Requires the caller to be in the same organization as the target user, or be an admin.
Request example
GET /users/AAAAAAAAAAAAAAAA
Authorization: Bearer <token>
Response example
{
"resource": {
"uri": "https://api.calendly.com/users/AAAAAAAAAAAAAAAA",
"name": "John Smith",
"email": "john@example.com"
}
}
List Organization Memberships
- Method: GET
- URL:
https://api.calendly.com/organization_memberships - Watch out for: This is the primary way to enumerate all users in an organization. Requires admin or owner token.
Request example
GET /organization_memberships?organization=https://api.calendly.com/organizations/BBBB&count=20
Authorization: Bearer <token>
Response example
{
"collection": [
{
"uri": "https://api.calendly.com/organization_memberships/CCCC",
"role": "admin",
"user": { "uri": "...", "email": "jane@example.com" }
}
],
"pagination": { "next_page_token": "abc123" }
}
Get Organization Membership
- Method: GET
- URL:
https://api.calendly.com/organization_memberships/{uuid} - Watch out for: Role changes are not supported via this endpoint; use the invite/remove flow.
Request example
GET /organization_memberships/CCCCCCCCCCCCCCCC
Authorization: Bearer <token>
Response example
{
"resource": {
"uri": "https://api.calendly.com/organization_memberships/CCCC",
"role": "user",
"user": { "name": "John", "email": "john@example.com" }
}
}
Invite User to Organization
- Method: POST
- URL:
https://api.calendly.com/organizations/{uuid}/invitations - Watch out for: This sends an email invitation; the user is not created until they accept. No way to force-provision without SCIM.
Request example
POST /organizations/BBBB/invitations
Authorization: Bearer <token>
Content-Type: application/json
{"email": "newuser@example.com"}
Response example
{
"resource": {
"uri": "https://api.calendly.com/organizations/BBBB/invitations/DDDD",
"email": "newuser@example.com",
"status": "pending"
}
}
Revoke Organization Invitation
- Method: DELETE
- URL:
https://api.calendly.com/organizations/{org_uuid}/invitations/{invitation_uuid} - Watch out for: Only pending invitations can be revoked. Accepted invitations require removing the membership instead.
Request example
DELETE /organizations/BBBB/invitations/DDDD
Authorization: Bearer <token>
Response example
HTTP 204 No Content
Remove Organization Membership (Delete User from Org)
- Method: DELETE
- URL:
https://api.calendly.com/organization_memberships/{uuid} - Watch out for: Removes the user from the organization but does not delete their Calendly account. Owner cannot be removed.
Request example
DELETE /organization_memberships/CCCCCCCCCCCCCCCC
Authorization: Bearer <token>
Response example
HTTP 204 No Content
List Organization Invitations
- Method: GET
- URL:
https://api.calendly.com/organizations/{uuid}/invitations - Watch out for: Filter by status (pending, accepted, declined) to narrow results.
Request example
GET /organizations/BBBB/invitations?count=20&status=pending
Authorization: Bearer <token>
Response example
{
"collection": [
{ "email": "pending@example.com", "status": "pending", "created_at": "2024-01-01T00:00:00Z" }
],
"pagination": { "next_page_token": null }
}
Rate limits, pagination, and events
- Rate limits: Calendly enforces per-minute rate limits per access token. Limits vary by plan tier.
- Rate-limit headers: Yes
- Retry-After header: Yes
- Rate-limit notes: Rate limit headers include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset. HTTP 429 is returned when exceeded; honor Retry-After header.
- Pagination method: cursor
- Default page size: 20
- Max page size: 100
- Pagination pointer: page_token
| Plan | Limit | Concurrent |
|---|---|---|
| Free / Standard / Teams | 60 requests/minute | 0 |
| Enterprise | 120 requests/minute | 0 |
- Webhooks available: Yes
- Webhook notes: Calendly supports webhook subscriptions for event lifecycle changes. Webhooks are created via the API and can be scoped to a user or organization.
- Alternative event strategy: Poll List Scheduled Events or List Organization Memberships for user-management changes if webhooks are insufficient.
- Webhook events: invitee.created, invitee.canceled, invitee_no_show.created, invitee_no_show.deleted, routing_form_submission.created
SCIM API status
SCIM available: Yes
SCIM version: 2.0
Plan required: Enterprise (minimum ~$15,000/year, 30+ users); SSO must be configured first.
Endpoint: https://auth.calendly.com/scim/v2
Supported operations: GET /Users (list users), GET /Users/{id} (get user), POST /Users (create/provision user), PUT /Users/{id} (replace user), PATCH /Users/{id} (update user attributes), DELETE /Users/{id} (deprovision user), GET /Groups (list groups), POST /Groups (create group), PATCH /Groups/{id} (update group membership), DELETE /Groups/{id} (delete group)
Limitations:
- Requires Enterprise plan and active SSO (Okta, Entra ID, or OneLogin).
- SCIM token is generated in Calendly admin settings and is separate from OAuth tokens.
- Google Workspace is not supported as an IdP for SCIM.
- Teams plan SSO add-on does not include SCIM provisioning.
- Deprovisioning via SCIM removes the user from the organization but does not delete their Calendly account data.
Common scenarios
For teams that need deeper lifecycle automation, Stitchflow's MCP server with ~100 deep IT/identity integrations covers the provisioning and deprovisioning flows that Calendly's REST API cannot handle natively.
Via REST, user creation is invitation-based only: POST /organizations/{uuid}/invitations sends an email and the user is not active until they accept, making immediate provisioning impossible without SCIM. SCIM 2.
0 is available at https://auth.calendly.com/scim/v2 but is gated to Enterprise (minimum ~$15,000/year, 30+ users) with an active SSO configuration on Okta, Entra ID, or OneLogin - Google Workspace is explicitly not supported as an IdP.
Role promotion (admin/user) is not available via the REST API at all; it requires either SCIM PATCH or the Calendly admin UI. For removal on non-Enterprise plans, DELETE /organization_memberships/{uuid} removes the user from the organization but leaves their Calendly account and personal data intact.
List all users in an organization
- Authenticate with an admin or owner OAuth token or PAT.
- Call GET /users/me to retrieve the current_organization URI.
- Call GET /organization_memberships?organization=
&count=100 to retrieve the first page of members. - If pagination.next_page_token is present, repeat with &page_token=
until exhausted. - Extract the nested user object from each membership record for email, name, role, etc.
Watch out for: The organization URI must be passed as a query parameter and must match exactly the URI returned by /users/me.
Provision a new user (Enterprise with SCIM)
- Ensure Enterprise plan and SSO are active; generate a SCIM token in Calendly Admin > Security.
- Configure your IdP (Okta, Entra ID, or OneLogin) with the SCIM base URL https://auth.calendly.com/scim/v2 and the SCIM token.
- Assign the user to the Calendly application in the IdP.
- The IdP sends POST /scim/v2/Users with userName (email), name, and active=true.
- Calendly provisions the user and returns a SCIM User object with the Calendly id.
Watch out for: If SSO is not yet configured, SCIM provisioning will fail. Google Workspace is not a supported IdP.
Remove a user from an organization (non-Enterprise)
- Authenticate with an admin or owner token.
- Call GET /organization_memberships?organization=
and find the membership URI for the target user by matching email. - Call DELETE /organization_memberships/
to remove the user. - Verify removal by confirming the membership no longer appears in subsequent list calls.
Watch out for: This removes the user from the organization only; their Calendly account and personal data remain. The organization owner cannot be removed via API.
Why building this yourself is a trap
The most significant API caveat is the invitation-acceptance dependency: any provisioning workflow that assumes a user is active immediately after the API call will break, because the seat is not consumed and the user does not appear as an active member until they click the email invite.
OAuth access tokens expire and require a refresh_token flow via POST https://auth.calendly.com/oauth/token with grant_type=refresh_token; Personal Access Tokens do not expire but are scoped to the generating user's permissions, making them fragile for org-wide admin operations if that user's role changes.
Webhook support covers scheduling lifecycle events (invitee.created, invitee.canceled, etc.) but does not emit events for membership changes - teams that need real-time deprovisioning signals must poll GET /organization_memberships on a schedule.
SCIM deprovisioning removes the user from the organization but does not delete their Calendly account data, which is a compliance consideration for organizations with strict data residency requirements.
Automate Calendly workflows without one-off scripts
Stitchflow builds and maintains end-to-end IT automation across your SaaS stack, including apps without APIs. Built for exactly how your company works, with human approvals where they matter.