Skip to content

Public scheduling API

The public scheduling API lets external requesters list visible meeting types and submit booking proposals through a public scheduling link.

Use it when you are building a requester-side integration, MCP tool, or partner workflow. If you are configuring links for calendar owners, the admin dashboard is the recommended control surface.

Overview

There are two API surfaces:

SurfaceBase pathWho uses it
Public requester API/public/...Anonymous or verified external requesters.
Admin public scheduling API/v1/public-scheduling/...Authenticated admin dashboard and admin clients.

Requester APIs never return private calendar details, hidden meeting types, internal proposal IDs, audit rows, or raw availability.

Authentication

Anonymous public scheduling does not require credentials.

Verified requester flows may include an optional requester credential:

Authorization: Bearer rc_1234abcd_...

Requester credentials prove external requester identity. They do not grant calendar access and do not replace owner policy.

Admin public scheduling APIs require an authenticated dashboard admin session. In personal accounts, the calendar owner is also the admin. In workspace accounts, non-admin members cannot list or mutate these configuration records in beta.

Public endpoints

EndpointPurpose
GET /public/schedules/{id}/meeting-typesList meeting types visible to the requester.
POST /public/schedules/{id}/booking-proposalsSubmit a public booking proposal.
GET /public/booking-proposals/{token}Poll the safe public status for a request.
POST /public/contact-verifications/{token}/confirmConfirm the requester contact email.
POST /public/booking-proposals/{token}/withdrawWithdraw a pending request.

{id} can be the public scheduling ID or the readable alias path used by the public URL.

Admin endpoints

The admin API backs the dashboard:

EndpointPurpose
GET /v1/public-scheduling/boundariesList public links.
POST /v1/public-scheduling/boundariesCreate a public link for one calendar owner.
PATCH /v1/public-scheduling/boundaries/{boundary_id}Update link path, free-text policy, or status.
GET /v1/public-scheduling/boundaries/{boundary_id}/meeting-typesList meeting types on a link.
POST /v1/public-scheduling/boundaries/{boundary_id}/meeting-typesCreate or publish a public meeting type.
PATCH /v1/public-scheduling/meeting-types/{meeting_type_id}Update meeting type policy or status.
GET /v1/public-scheduling/verified-domainsList DNS verification challenges.
POST /v1/public-scheduling/verified-domainsCreate a DNS verification challenge.
POST /v1/public-scheduling/verified-domains/{id}/checkRe-check DNS verification.
DELETE /v1/public-scheduling/verified-domains/{id}Remove an unused domain.
GET /v1/public-scheduling/requester-identitiesList requester identities.
POST /v1/public-scheduling/requester-identitiesCreate a requester identity.
GET /v1/public-scheduling/requester-identities/{id}/credentialsList credential metadata.
POST /v1/public-scheduling/requester-identities/{id}/credentialsIssue a one-time requester credential secret.
POST /v1/public-scheduling/requester-credentials/{id}/revokeRevoke a requester credential.
GET /v1/public-scheduling/requester-audiencesList audiences.
POST /v1/public-scheduling/requester-audiencesCreate an audience.
POST /v1/public-scheduling/requester-audiences/{id}/membersAdd a domain, identity, or pending domain to an audience.
GET /v1/public-scheduling/meeting-types/{meeting_type_id}/allocationsList allocations for a meeting type.
POST /v1/public-scheduling/meeting-types/{meeting_type_id}/allocationsCreate an allocation.
PATCH /v1/public-scheduling/allocations/{allocation_id}Update or disable an allocation.
GET /v1/public-scheduling/security-eventsList public scheduling security and abuse events.

These endpoints use internal resource names like boundary because they mirror the API and database model. The dashboard translates that to public link for admins configuring owner-facing links.

Security events

Admins can inspect public scheduling abuse and policy events with:

GET /v1/public-scheduling/security-events

Optional filters:

QueryMeaning
boundary_idLimit to one public link.
event_typeLimit to one event type.
reasonLimit to one reason.
from / toISO 8601 time range.
cursorContinue pagination.
page_sizeNumber of rows to return.

Rows include the event type, reason, related public link, meeting type, requester identity, verified domain, IP hash, user agent, and metadata. They are admin-visible operational signals, not requester-facing status.

Suggested times

GET /public/schedules/{id}/meeting-types can return suggested_times on visible meeting types:

{
  "public_meeting_type": "intro-call",
  "name": "Intro call",
  "duration_minutes": 30,
  "suggested_times": [
    {
      "start": "2026-07-08T14:00:00.000Z",
      "end": "2026-07-08T14:30:00.000Z",
      "rank": 1,
      "source": "allocation"
    }
  ]
}

Suggested times are not holds. Submit the chosen start/end inside requested_window; Openavail rechecks availability before accepting the request.

Status and withdrawal

A successful public proposal response includes a status_url. Anonymous proposals may also include a contact_verification_url.

Safe public statuses include:

StatusMeaning
pending_reviewWaiting for owner review.
pending_requester_verificationWaiting for contact confirmation.
bookedThe request became a booking.
rejectedThe owner or policy rejected it.
expiredThe request expired.
withdrawnThe requester withdrew it.
counteredThe owner asked for a different path forward.
needs_more_informationThe owner needs more requester context.

Requesters can withdraw while the request is still pending review or pending requester verification.

Errors

Public scheduling errors use the normal Openavail error envelope:

{
  "error": {
    "code": "attendee_limit_exceeded",
    "message": "Attendee limit is 1"
  },
  "pending_notifications": []
}

See Error codes for public scheduling-specific error codes.