{"openapi":"3.1.0","info":{"title":"Daycal API","version":"1.0.0","description":"Daycal gives a person a page where other people can book time with them, matching their real situation (trips in other time zones, holidays, Friday cutoffs, focus blocks, daily limits, several calendars) because they just tell their AI assistant. This API serves both kinds of assistant. The public booking API (tag public, no auth) is for an invitee's assistant booking a time on someone's page. The owner API (tag owner; Bearer: an MCP OAuth access token or a Daycal API token from /token) is for the owner's assistant: under the hood, availability is a short rules.js written against the daycal standard library, which the assistant writes and maintains, always previewing and getting the owner's go-ahead before making it live. Every MCP tool (connecting calendars, importing from Calendly or Cal.com, the handle, account deletion and the rest) is also a REST call: GET /api/me/tools lists them with their input schemas, plus the instructions every MCP client gets (read and follow them first) and the prompts as text (setup: first-time setup step by step); POST /api/me/tools/{name} runs one. Times are ISO 8601 in UTC."},"servers":[{"url":"https://daycal.io"}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"OAuth access token or Daycal API token (daycal_...). Its owner scopes decide which tools and routes it reaches: read, write (includes read), billing, secrets; GET /api/me/tools lists the tools it may call."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"alternatives":{"type":"array","items":{"$ref":"#/components/schemas/Slot"},"description":"slot_taken (public API): the nearest open slots"},"triesLeft":{"type":"integer","description":"wrong_code (public API): wrong codes the request still takes"},"details":{"description":"Machine-readable detail, e.g. invalid_rules' RuleError (owner API)"}},"required":["code","message"]}},"required":["error"]},"BearerError":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}},"required":["error"]},"Slot":{"type":"object","properties":{"start":{"type":"string","format":"date-time"},"end":{"type":"string","format":"date-time"}},"required":["start","end"]},"Page":{"type":"object","properties":{"handle":{"type":"string"},"ownerName":{"type":"string"},"timezone":{"type":"string"},"eventTypes":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"duration":{"type":"integer","description":"Minutes"},"location":{"type":["string","null"]},"conferencing":{"type":"string","enum":["google-meet","link","none"]}},"required":["slug","title","description","duration","location","conferencing"]}},"booking":{"type":"object","properties":{"note":{"type":"boolean"},"confirmation":{"type":"string"}},"required":["note","confirmation"]},"footer":{"type":"boolean"},"turnstileSiteKey":{"type":["string","null"]},"pageId":{"type":"string","description":"Opaque; send it back as the booking's pageId"}},"required":["handle","ownerName","timezone","eventTypes","booking","footer","turnstileSiteKey","pageId"]},"Booking":{"type":"object","properties":{"id":{"type":"string"},"start":{"type":"string","format":"date-time"},"end":{"type":"string","format":"date-time"},"eventType":{"type":"string"},"title":{"type":"string"},"manageUrl":{"type":"string"},"conferenceUrl":{"type":["string","null"]},"status":{"type":"string","enum":["confirmed","cancelled","rescheduled"]}},"required":["id","start","end","eventType","title","manageUrl","conferenceUrl","status"]},"Booked":{"type":"object","properties":{"booking":{"$ref":"#/components/schemas/Booking"},"confirmation":{"type":"string"}},"required":["booking","confirmation"]},"ManagedBooking":{"type":"object","properties":{"id":{"type":"string"},"start":{"type":"string","format":"date-time"},"end":{"type":"string","format":"date-time"},"eventType":{"type":"string"},"title":{"type":"string"},"manageUrl":{"type":"string"},"conferenceUrl":{"type":["string","null"]},"status":{"type":"string","enum":["confirmed","cancelled","rescheduled"]},"inviteeName":{"type":"string"},"inviteeEmail":{"type":"string"},"note":{"type":["string","null"]}},"required":["id","start","end","eventType","title","manageUrl","conferenceUrl","status","inviteeName","inviteeEmail","note"]},"ManagedPage":{"type":"object","properties":{"handle":{"type":["string","null"],"description":"null while the account holds no handle: no page to book again on"},"ownerName":{"type":"string"},"timezone":{"type":"string"},"eventTypes":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"duration":{"type":"integer","description":"Minutes"},"location":{"type":["string","null"]},"conferencing":{"type":"string","enum":["google-meet","link","none"]}},"required":["slug","title","description","duration","location","conferencing"]}},"booking":{"type":"object","properties":{"note":{"type":"boolean"},"confirmation":{"type":"string"}},"required":["note","confirmation"]},"footer":{"type":"boolean"},"turnstileSiteKey":{"type":["string","null"]}},"required":["handle","ownerName","timezone","eventTypes","booking","footer","turnstileSiteKey"]}}},"paths":{"/api/pages/{handle}":{"get":{"tags":["public"],"summary":"Booking page and its event types","parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Page"}}}},"429":{"description":"Rate limited. Retry-After is set when a rate-limit window is spent (not on a booking's own budget)","headers":{"Retry-After":{"description":"Seconds until the rate-limit window resets","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/pages/{handle}/slots":{"get":{"tags":["public"],"summary":"Open slots for one event type (to - from <= 35 days)","parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string"}},{"name":"type","in":"query","required":true,"schema":{"type":"string"},"description":"Event type slug"},{"name":"from","in":"query","required":true,"schema":{"type":"string"},"description":"ISO instant"},{"name":"to","in":"query","required":true,"schema":{"type":"string"},"description":"ISO instant"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"slots":{"type":"array","items":{"$ref":"#/components/schemas/Slot"}},"timezone":{"type":"string"},"configVersion":{"type":"integer"},"eventsVersion":{"type":"integer"},"stale":{"type":"boolean"}},"required":["slots","timezone","configVersion","eventsVersion","stale"]}}}},"429":{"description":"Rate limited. Retry-After is set when a rate-limit window is spent (not on a booking's own budget)","headers":{"Retry-After":{"description":"Seconds until the rate-limit window resets","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/pages/{handle}/bookings":{"post":{"tags":["public"],"summary":"Book a slot, one of four ways, each checked the same way. With invite (a booking link's token, from ?invite= on the link the page's owner gave): booked, 201. With turnstileToken (the booking page's form): booked, 201. Signed by an allowlisted operator's agent (Web Bot Auth: Signature, Signature-Input and Signature-Agent headers from https://chatgpt.com or https://agent.bot.goog): booked, 201, whatever the body's turnstileToken. With none of these (an invitee's agent): nothing is booked or held; a 6-digit code is emailed to email, 202, and POST /api/pages/{handle}/bookings/confirm books. 409 slot_taken carries alternatives; 409 page_changed: the handle moved since the page was read (pageId).","parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"eventType":{"type":"string"},"start":{"type":"string","format":"date-time"},"name":{"type":"string"},"email":{"type":"string"},"note":{"type":"string"},"tz":{"type":"string"},"pageId":{"type":"string","description":"The pageId GET /api/pages/{handle} gave: read the page first and send it on every booking, so a handle that names another account now is refused (409 page_changed) rather than booked with them. Required (400 invalid_request without it), except with invite: a booking link's token names its owner"},"invite":{"type":"string","description":"A booking link's token: books once, no bot check, no code"},"turnstileToken":{"type":"string","description":"Solved by the booking page's form only"}},"required":["eventType","start","name","email","tz"],"anyOf":[{"required":["pageId"]},{"required":["invite"]}]},"example":{"eventType":"30min","start":"2026-10-20T16:00:00Z","name":"Dana Park","email":"dana@example.com","tz":"America/New_York","pageId":"<pageId from GET /api/pages/{handle}>"}}}},"responses":{"201":{"description":"Booked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Booked"}}}},"202":{"description":"Code emailed to the invitee (10 minutes, 5 tries); nothing is booked or held yet","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["confirm_email"]},"confirmation":{"type":"string","description":"Pass to /bookings/confirm with the emailed code"},"expiresAt":{"type":"string","format":"date-time"}},"required":["status","confirmation","expiresAt"]}}}},"429":{"description":"Rate limited. Retry-After is set when a rate-limit window is spent (not on a booking's own budget)","headers":{"Retry-After":{"description":"Seconds until the rate-limit window resets","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/pages/{handle}/bookings/confirm":{"post":{"tags":["public"],"summary":"Book the request a 202 named, with the code emailed to the invitee: checked again now, as any booking. 403 wrong_code (triesLeft), 404 confirmation_not_found (used, replaced, closed or expired), 409 slot_taken.","parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"confirmation":{"type":"string"},"code":{"type":"string"}},"required":["confirmation","code"]}}}},"responses":{"201":{"description":"Booked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Booked"}}}},"429":{"description":"Rate limited. Retry-After is set when a rate-limit window is spent (not on a booking's own budget)","headers":{"Retry-After":{"description":"Seconds until the rate-limit window resets","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/b/{token}":{"get":{"tags":["public"],"summary":"A booking by its manage token","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"booking":{"$ref":"#/components/schemas/ManagedBooking"},"page":{"$ref":"#/components/schemas/ManagedPage"}},"required":["booking","page"]}}}},"429":{"description":"Rate limited. Retry-After is set when a rate-limit window is spent (not on a booking's own budget)","headers":{"Retry-After":{"description":"Seconds until the rate-limit window resets","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/b/{token}/reschedule":{"post":{"tags":["public"],"summary":"Move a booking","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"start":{"type":"string","format":"date-time"},"tz":{"type":"string"}},"required":["start","tz"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"booking":{"$ref":"#/components/schemas/Booking"}},"required":["booking"]}}}},"429":{"description":"Rate limited. Retry-After is set when a rate-limit window is spent (not on a booking's own budget)","headers":{"Retry-After":{"description":"Seconds until the rate-limit window resets","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/b/{token}/cancel":{"post":{"tags":["public"],"summary":"Cancel a booking","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string"}},"required":[]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"booking":{"$ref":"#/components/schemas/Booking"}},"required":["booking"]}}}},"429":{"description":"Rate limited. Retry-After is set when a rate-limit window is spent (not on a booking's own budget)","headers":{"Retry-After":{"description":"Seconds until the rate-limit window resets","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me":{"get":{"security":[{"bearer":[]}],"tags":["owner"],"summary":"Owner, handle, plan, live version, warnings, and the calendar connections that need the owner","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"warnings":{"type":"array","items":{"type":"string"}},"attention":{"type":"array","description":"Calendar connections that need the owner, most severe first","items":{"type":"object","properties":{"label":{"type":"string"},"state":{"type":"string","enum":["limited","expiring","revoked","blocked"]},"missing":{"type":"array","items":{"type":"string"},"description":"Google scopes the reconnect asks for"},"reconnectUrl":{"type":["string","null"],"description":"Give it to the owner as is: it opens Daycal, then Google"},"since":{"type":["string","null"],"format":"date-time"},"waiting":{"type":"integer","description":"Bookings whose calendar writes wait on this connection"}},"required":["label","state","missing","reconnectUrl","since","waiting"]}}},"required":["warnings","attention"]}}}},"401":{"description":"Missing, unknown, expired or revoked token: sign in again (RFC 6750 invalid_token)","headers":{"WWW-Authenticate":{"description":"Bearer challenge with resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"403":{"description":"Outside this token's access (RFC 6750 insufficient_scope): the owner scopes are read, write, billing and secrets; the challenge names the ones to sign in again for","headers":{"WWW-Authenticate":{"description":"Bearer challenge with error, scope and resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"429":{"description":"Rate limited. Retry-After is set when a rate-limit window is spent (not on a booking's own budget)","headers":{"Retry-After":{"description":"Seconds until the rate-limit window resets","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/calendars":{"get":{"security":[{"bearer":[]}],"tags":["owner"],"summary":"Calendars across connections with stdlib refs","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array"}}},"headers":{"Daycal-Warning":{"description":"One per calendar connection that needs the owner (repeated): what is wrong, what still works, the owner's action. Ends with 'Link: GET /api/me', which has the reconnect link. Sent only to a credential holding the read scope.","schema":{"type":"string"}}}},"401":{"description":"Missing, unknown, expired or revoked token: sign in again (RFC 6750 invalid_token)","headers":{"WWW-Authenticate":{"description":"Bearer challenge with resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"403":{"description":"Outside this token's access (RFC 6750 insufficient_scope): the owner scopes are read, write, billing and secrets; the challenge names the ones to sign in again for","headers":{"WWW-Authenticate":{"description":"Bearer challenge with error, scope and resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"429":{"description":"Rate limited. Retry-After is set when a rate-limit window is spent (not on a booking's own budget)","headers":{"Retry-After":{"description":"Seconds until the rate-limit window resets","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/versions":{"get":{"security":[{"bearer":[]}],"tags":["owner"],"summary":"Config history","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array"}}},"headers":{"Daycal-Warning":{"description":"One per calendar connection that needs the owner (repeated): what is wrong, what still works, the owner's action. Ends with 'Link: GET /api/me', which has the reconnect link. Sent only to a credential holding the read scope.","schema":{"type":"string"}}}},"401":{"description":"Missing, unknown, expired or revoked token: sign in again (RFC 6750 invalid_token)","headers":{"WWW-Authenticate":{"description":"Bearer challenge with resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"403":{"description":"Outside this token's access (RFC 6750 insufficient_scope): the owner scopes are read, write, billing and secrets; the challenge names the ones to sign in again for","headers":{"WWW-Authenticate":{"description":"Bearer challenge with error, scope and resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"429":{"description":"Rate limited. Retry-After is set when a rate-limit window is spent (not on a booking's own budget)","headers":{"Retry-After":{"description":"Seconds until the rate-limit window resets","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"security":[{"bearer":[]}],"tags":["owner"],"summary":"Upload rules.js; validates and stores a draft version. activate: true also makes it live and requires previewId from a passing preview of exactly this rulesJs (30 minutes; 409 preview_required otherwise)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"rulesJs":{"type":"string"},"note":{"type":"string"},"activate":{"type":"boolean"},"previewId":{"type":"string"}},"required":["rulesJs"]}}}},"responses":{"201":{"description":"Stored","content":{"application/json":{"schema":{"type":"object","properties":{"versionId":{"type":"integer"},"bookingUrl":{"type":"string"},"handle":{"type":"string"},"warnings":{"type":"array","items":{"type":"string"}},"planNote":{"type":"string","description":"Free plan only, at most weekly: the one note about Pro"}},"required":[]}}},"headers":{"Daycal-Warning":{"description":"One per calendar connection that needs the owner (repeated): what is wrong, what still works, the owner's action. Ends with 'Link: GET /api/me', which has the reconnect link. Sent only to a credential holding the read scope.","schema":{"type":"string"}}}},"401":{"description":"Missing, unknown, expired or revoked token: sign in again (RFC 6750 invalid_token)","headers":{"WWW-Authenticate":{"description":"Bearer challenge with resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"403":{"description":"Outside this token's access (RFC 6750 insufficient_scope): the owner scopes are read, write, billing and secrets; the challenge names the ones to sign in again for","headers":{"WWW-Authenticate":{"description":"Bearer challenge with error, scope and resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"429":{"description":"Rate limited. Retry-After is set when a rate-limit window is spent (not on a booking's own budget)","headers":{"Retry-After":{"description":"Seconds until the rate-limit window resets","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/versions/{id}":{"get":{"security":[{"bearer":[]}],"tags":["owner"],"summary":"One version with its rules.js","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}},"headers":{"Daycal-Warning":{"description":"One per calendar connection that needs the owner (repeated): what is wrong, what still works, the owner's action. Ends with 'Link: GET /api/me', which has the reconnect link. Sent only to a credential holding the read scope.","schema":{"type":"string"}}}},"401":{"description":"Missing, unknown, expired or revoked token: sign in again (RFC 6750 invalid_token)","headers":{"WWW-Authenticate":{"description":"Bearer challenge with resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"403":{"description":"Outside this token's access (RFC 6750 insufficient_scope): the owner scopes are read, write, billing and secrets; the challenge names the ones to sign in again for","headers":{"WWW-Authenticate":{"description":"Bearer challenge with error, scope and resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"429":{"description":"Rate limited. Retry-After is set when a rate-limit window is spent (not on a booking's own budget)","headers":{"Retry-After":{"description":"Seconds until the rate-limit window resets","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/versions/{id}/activate":{"post":{"security":[{"bearer":[]}],"tags":["owner"],"summary":"Make a version live. A version that was live before and keeps the current handle (rollback) needs no body; a draft, or a version with a different handle, needs { previewId } from a passing preview of it (409 preview_required otherwise)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"previewId":{"type":"string"}},"required":[]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}},"headers":{"Daycal-Warning":{"description":"One per calendar connection that needs the owner (repeated): what is wrong, what still works, the owner's action. Ends with 'Link: GET /api/me', which has the reconnect link. Sent only to a credential holding the read scope.","schema":{"type":"string"}}}},"401":{"description":"Missing, unknown, expired or revoked token: sign in again (RFC 6750 invalid_token)","headers":{"WWW-Authenticate":{"description":"Bearer challenge with resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"403":{"description":"Outside this token's access (RFC 6750 insufficient_scope): the owner scopes are read, write, billing and secrets; the challenge names the ones to sign in again for","headers":{"WWW-Authenticate":{"description":"Bearer challenge with error, scope and resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"429":{"description":"Rate limited. Retry-After is set when a rate-limit window is spent (not on a booking's own budget)","headers":{"Retry-After":{"description":"Seconds until the rate-limit window resets","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/preview":{"post":{"security":[{"bearer":[]}],"tags":["owner"],"summary":"Run inline rules.js or a stored version against live events; slots per event type, a diff against live, and (when ok) a previewId for going live with exactly that source","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"rulesJs":{"type":"string"},"versionId":{"type":"integer"},"days":{"type":"integer","minimum":1,"maximum":30},"eventType":{"type":"string"}},"required":[]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}},"headers":{"Daycal-Warning":{"description":"One per calendar connection that needs the owner (repeated): what is wrong, what still works, the owner's action. Ends with 'Link: GET /api/me', which has the reconnect link. Sent only to a credential holding the read scope.","schema":{"type":"string"}}}},"401":{"description":"Missing, unknown, expired or revoked token: sign in again (RFC 6750 invalid_token)","headers":{"WWW-Authenticate":{"description":"Bearer challenge with resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"403":{"description":"Outside this token's access (RFC 6750 insufficient_scope): the owner scopes are read, write, billing and secrets; the challenge names the ones to sign in again for","headers":{"WWW-Authenticate":{"description":"Bearer challenge with error, scope and resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"429":{"description":"Rate limited. Retry-After is set when a rate-limit window is spent (not on a booking's own budget)","headers":{"Retry-After":{"description":"Seconds until the rate-limit window resets","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/bookings":{"get":{"security":[{"bearer":[]}],"tags":["owner"],"summary":"Bookings (upcoming=false for all)","parameters":[{"name":"upcoming","in":"query","required":false,"schema":{"type":"string"},"description":"true (default) or false"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array"}}},"headers":{"Daycal-Warning":{"description":"One per calendar connection that needs the owner (repeated): what is wrong, what still works, the owner's action. Ends with 'Link: GET /api/me', which has the reconnect link. Sent only to a credential holding the read scope.","schema":{"type":"string"}}}},"401":{"description":"Missing, unknown, expired or revoked token: sign in again (RFC 6750 invalid_token)","headers":{"WWW-Authenticate":{"description":"Bearer challenge with resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"403":{"description":"Outside this token's access (RFC 6750 insufficient_scope): the owner scopes are read, write, billing and secrets; the challenge names the ones to sign in again for","headers":{"WWW-Authenticate":{"description":"Bearer challenge with error, scope and resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"429":{"description":"Rate limited. Retry-After is set when a rate-limit window is spent (not on a booking's own budget)","headers":{"Retry-After":{"description":"Seconds until the rate-limit window resets","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/bookings/{id}/cancel":{"post":{"security":[{"bearer":[]}],"tags":["owner"],"summary":"Cancel a booking","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}},"headers":{"Daycal-Warning":{"description":"One per calendar connection that needs the owner (repeated): what is wrong, what still works, the owner's action. Ends with 'Link: GET /api/me', which has the reconnect link. Sent only to a credential holding the read scope.","schema":{"type":"string"}}}},"401":{"description":"Missing, unknown, expired or revoked token: sign in again (RFC 6750 invalid_token)","headers":{"WWW-Authenticate":{"description":"Bearer challenge with resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"403":{"description":"Outside this token's access (RFC 6750 insufficient_scope): the owner scopes are read, write, billing and secrets; the challenge names the ones to sign in again for","headers":{"WWW-Authenticate":{"description":"Bearer challenge with error, scope and resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"429":{"description":"Rate limited. Retry-After is set when a rate-limit window is spent (not on a booking's own budget)","headers":{"Retry-After":{"description":"Seconds until the rate-limit window resets","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/errors":{"get":{"security":[{"bearer":[]}],"tags":["owner"],"summary":"Recent rules.js errors","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array"}}},"headers":{"Daycal-Warning":{"description":"One per calendar connection that needs the owner (repeated): what is wrong, what still works, the owner's action. Ends with 'Link: GET /api/me', which has the reconnect link. Sent only to a credential holding the read scope.","schema":{"type":"string"}}}},"401":{"description":"Missing, unknown, expired or revoked token: sign in again (RFC 6750 invalid_token)","headers":{"WWW-Authenticate":{"description":"Bearer challenge with resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"403":{"description":"Outside this token's access (RFC 6750 insufficient_scope): the owner scopes are read, write, billing and secrets; the challenge names the ones to sign in again for","headers":{"WWW-Authenticate":{"description":"Bearer challenge with error, scope and resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"429":{"description":"Rate limited. Retry-After is set when a rate-limit window is spent (not on a booking's own budget)","headers":{"Retry-After":{"description":"Seconds until the rate-limit window resets","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/sync":{"post":{"security":[{"bearer":[]}],"tags":["owner"],"summary":"Force a full calendar sync","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}},"headers":{"Daycal-Warning":{"description":"One per calendar connection that needs the owner (repeated): what is wrong, what still works, the owner's action. Ends with 'Link: GET /api/me', which has the reconnect link. Sent only to a credential holding the read scope.","schema":{"type":"string"}}}},"401":{"description":"Missing, unknown, expired or revoked token: sign in again (RFC 6750 invalid_token)","headers":{"WWW-Authenticate":{"description":"Bearer challenge with resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"403":{"description":"Outside this token's access (RFC 6750 insufficient_scope): the owner scopes are read, write, billing and secrets; the challenge names the ones to sign in again for","headers":{"WWW-Authenticate":{"description":"Bearer challenge with error, scope and resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"429":{"description":"Rate limited. Retry-After is set when a rate-limit window is spent (not on a booking's own budget)","headers":{"Retry-After":{"description":"Seconds until the rate-limit window resets","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/tools":{"get":{"security":[{"bearer":[]}],"tags":["owner"],"summary":"Every owner tool this token may call (the same ones /mcp lists to it): name, title, description, annotations, and inputSchema, the JSON Schema of its arguments. Also instructions, the rules MCP clients get at initialize (follow them: which fields are untrusted data, which links are Daycal's, previewing before a push), and prompts, the MCP prompts as text (setup: first-time setup step by step)","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"instructions":{"type":"string"},"prompts":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"text":{"type":"string"}},"required":["name","description","text"]}},"tools":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"inputSchema":{"type":"object"},"annotations":{"type":"object"}},"required":["name","title","description","inputSchema","annotations"]}}},"required":["instructions","prompts","tools"]}}},"headers":{"Daycal-Warning":{"description":"One per calendar connection that needs the owner (repeated): what is wrong, what still works, the owner's action. Ends with 'Link: GET /api/me', which has the reconnect link. Sent only to a credential holding the read scope.","schema":{"type":"string"}}}},"401":{"description":"Missing, unknown, expired or revoked token: sign in again (RFC 6750 invalid_token)","headers":{"WWW-Authenticate":{"description":"Bearer challenge with resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"403":{"description":"Outside this token's access (RFC 6750 insufficient_scope): the owner scopes are read, write, billing and secrets; the challenge names the ones to sign in again for","headers":{"WWW-Authenticate":{"description":"Bearer challenge with error, scope and resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"429":{"description":"Rate limited. Retry-After is set when a rate-limit window is spent (not on a booking's own budget)","headers":{"Retry-After":{"description":"Seconds until the rate-limit window resets","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/tools/{name}":{"post":{"security":[{"bearer":[]}],"tags":["owner"],"summary":"Run one tool, exactly as the MCP tools/call of the same name: the body is its arguments (its inputSchema; no body for none), the response its output. 404 for no such tool, 400 invalid_body for arguments its inputSchema refuses; a refused call is the error it gives over MCP","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","enum":["get_types","set_handle","connect","list_connections","remove_connection","list_calendars","get_calendar_refs","preview","push_config","list_versions","activate_version","list_bookings","cancel_booking","get_errors","sync_now","get_logs","list_agents","revoke_agent","explain","delete_account","export_my_data","migrate","upgrade","billing_status","cancel_plan","get_skill","get_webhook_secret","create_booking_link","list_booking_links","revoke_booking_link"]}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"The tool's output","content":{"application/json":{"schema":{}}},"headers":{"Daycal-Warning":{"description":"One per calendar connection that needs the owner (repeated): what is wrong, what still works, the owner's action. Ends with 'Link: GET /api/me', which has the reconnect link. Sent only to a credential holding the read scope.","schema":{"type":"string"}}}},"401":{"description":"Missing, unknown, expired or revoked token: sign in again (RFC 6750 invalid_token)","headers":{"WWW-Authenticate":{"description":"Bearer challenge with resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"403":{"description":"Outside this token's access (RFC 6750 insufficient_scope): the owner scopes are read, write, billing and secrets; the challenge names the ones to sign in again for","headers":{"WWW-Authenticate":{"description":"Bearer challenge with error, scope and resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"429":{"description":"Rate limited. Retry-After is set when a rate-limit window is spent (not on a booking's own budget)","headers":{"Retry-After":{"description":"Seconds until the rate-limit window resets","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/billing":{"get":{"security":[{"bearer":[]}],"tags":["owner"],"summary":"Plan, renewal or expiry, the plans with their prices, and the Customer Portal link (null without the billing scope): billing_status","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"plan":{"type":"string","enum":["free","pro"]},"renews":{"type":["string","null"],"format":"date-time"},"expires":{"type":["string","null"],"format":"date-time"},"portalUrl":{"type":["string","null"]},"plans":{"type":"object"}},"required":["plan","renews","expires","portalUrl","plans"]}}},"headers":{"Daycal-Warning":{"description":"One per calendar connection that needs the owner (repeated): what is wrong, what still works, the owner's action. Ends with 'Link: GET /api/me', which has the reconnect link. Sent only to a credential holding the read scope.","schema":{"type":"string"}}}},"401":{"description":"Missing, unknown, expired or revoked token: sign in again (RFC 6750 invalid_token)","headers":{"WWW-Authenticate":{"description":"Bearer challenge with resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"403":{"description":"Outside this token's access (RFC 6750 insufficient_scope): the owner scopes are read, write, billing and secrets; the challenge names the ones to sign in again for","headers":{"WWW-Authenticate":{"description":"Bearer challenge with error, scope and resource_metadata","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerError"}}}},"429":{"description":"Rate limited. Retry-After is set when a rate-limit window is spent (not on a booking's own budget)","headers":{"Retry-After":{"description":"Seconds until the rate-limit window resets","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}