{"openapi":"3.1.0","info":{"title":"Caledee Public API","version":"v2","description":"REST API for Caledee — list event types, compute availability, create / cancel bookings, read leads and contacts, and inspect the authenticated user. Authenticated via Personal Access Tokens (PATs); see /docs/api.","contact":{"name":"Caledee support","email":"hello@caledee.com"},"license":{"name":"Commercial — see Terms"}},"servers":[{"url":"http://localhost:3000/api/v2","description":"Production"},{"url":"https://staging.caledee.com/api/v2","description":"Staging"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"PAT","description":"Personal Access Token, prefixed `pat_`. Mint one in Settings → Security → Access tokens. Send as `Authorization: Bearer pat_...`."}},"headers":{"XRateLimitLimit":{"description":"Requests permitted per minute for this token.","schema":{"type":"integer","example":600}},"XRateLimitRemaining":{"description":"Requests left in the current window.","schema":{"type":"integer","example":432}},"XRateLimitReset":{"description":"Unix epoch seconds when the window resets.","schema":{"type":"integer","example":1779296400}}},"schemas":{"Error":{"type":"object","required":["title","message"],"properties":{"title":{"type":"string","example":"Invalid Argument"},"message":{"type":"string","example":"`to` must be after `from`."},"details":{"type":"array","items":{"type":"object"},"description":"Zod issue details when the error is 400."}}},"User":{"type":"object","properties":{"id":{"type":"string","example":"cmpabc123"},"email":{"type":"string","format":"email"},"name":{"type":"string","nullable":true},"slug":{"type":"string","example":"imad"},"timezone":{"type":"string","example":"Europe/Paris"}}},"EventType":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"url":{"type":"string","format":"uri"},"kind":{"type":"string","enum":["one_on_one","round_robin","collective"]},"durationsMin":{"type":"array","items":{"type":"integer"}},"bufferBeforeMin":{"type":"integer"},"bufferAfterMin":{"type":"integer"},"color":{"type":"string"},"active":{"type":"boolean"},"secret":{"type":"boolean"},"organizationId":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"Slot":{"type":"object","properties":{"start":{"type":"string","format":"date-time"},"end":{"type":"string","format":"date-time"}}},"Booking":{"type":"object","properties":{"id":{"type":"string"},"eventType":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"}}},"startAt":{"type":"string","format":"date-time"},"endAt":{"type":"string","format":"date-time"},"durationMin":{"type":"integer"},"status":{"type":"string","enum":["active","canceled"]},"location":{"type":"object","nullable":true,"properties":{"kind":{"type":"string"},"value":{"type":"string","nullable":true}}},"invitee":{"type":"object","nullable":true,"properties":{"name":{"type":"string"},"email":{"type":"string","format":"email"},"timezone":{"type":"string"}}},"canceledAt":{"type":"string","format":"date-time","nullable":true},"cancelReason":{"type":"string","nullable":true},"canceledBy":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"}}},"Lead":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","nullable":true},"email":{"type":"string","format":"email"},"timezone":{"type":"string","example":"Europe/Paris"},"status":{"type":"string","enum":["new","contacted","qualified","lost"]},"eventType":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"}}},"booked":{"type":"boolean","description":"True once the lead converted into a booking."},"bookingId":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"},"completedAt":{"type":"string","format":"date-time","nullable":true}}},"Contact":{"type":"object","description":"A person, merged across every invitee and captured lead by email.","properties":{"email":{"type":"string","format":"email"},"name":{"type":"string","nullable":true},"kind":{"type":"string","enum":["client","lead"],"description":"client = has booked; lead = details only."},"status":{"type":"string","description":"Pipeline status for leads; `client` once they've booked."},"meetings":{"type":"integer","description":"Active (non-canceled) bookings."},"noShows":{"type":"integer"},"lastActivityAt":{"type":"string","format":"date-time","nullable":true},"firstSeenAt":{"type":"string","format":"date-time","nullable":true}}}},"responses":{"Unauthorized":{"description":"Missing or invalid PAT.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests for this token.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"Retry-After":{"schema":{"type":"integer","description":"Seconds."}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"security":[{"bearerAuth":[]}],"paths":{"/me":{"get":{"summary":"Get the authenticated user","tags":["Profile"],"security":[{"bearerAuth":["read:profile"]}],"responses":{"200":{"description":"Authenticated user.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/event-types":{"get":{"summary":"List the authenticated user's event types","tags":["Event types"],"security":[{"bearerAuth":["read:event-types"]}],"responses":{"200":{"description":"Event types.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EventType"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/availability":{"get":{"summary":"Compute bookable slots for one of the authenticated user's event types","tags":["Availability"],"security":[{"bearerAuth":["read:availability"]}],"parameters":[{"name":"eventTypeId","in":"query","required":true,"schema":{"type":"string"}},{"name":"from","in":"query","required":true,"schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","required":true,"schema":{"type":"string","format":"date-time"}},{"name":"tz","in":"query","schema":{"type":"string","example":"Europe/Paris"}},{"name":"duration","in":"query","schema":{"type":"integer"}}],"responses":{"200":{"description":"Bookable slot list.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Slot"}}}}}}},"400":{"description":"Invalid arguments."},"404":{"description":"Event type not found."},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/bookings":{"get":{"summary":"List bookings on the authenticated user's event types","tags":["Bookings"],"security":[{"bearerAuth":["read:bookings"]}],"parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["active","canceled"]}},{"name":"from","in":"query","description":"Only bookings starting at/after this RFC 3339 datetime.","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","description":"Only bookings starting at/before this RFC 3339 datetime.","schema":{"type":"string","format":"date-time"}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":100}}],"responses":{"200":{"description":"Paginated bookings.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Booking"}},"nextCursor":{"type":"string","nullable":true}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"summary":"Create a booking on the authenticated user's event type","tags":["Bookings"],"security":[{"bearerAuth":["write:bookings"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["eventTypeId","start","durationMin","invitee"],"properties":{"eventTypeId":{"type":"string"},"start":{"type":"string","format":"date-time"},"durationMin":{"type":"integer"},"invitee":{"type":"object","required":["name","email","timezone"],"properties":{"name":{"type":"string"},"email":{"type":"string","format":"email"},"timezone":{"type":"string"},"textReminderNumber":{"type":"string"},"smsOptIn":{"type":"boolean"}}},"answers":{"type":"array","items":{"type":"object","properties":{"questionId":{"type":"string"},"value":{"type":"string"}}}},"guests":{"type":"array","items":{"type":"string","format":"email"}},"notes":{"type":"string"},"locationInput":{"type":"string"}}}}}},"responses":{"201":{"description":"Booking created."},"400":{"description":"Invalid request."},"404":{"description":"Event type not found."},"409":{"description":"Slot unavailable or event-type inactive."},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/bookings/{id}":{"delete":{"summary":"Cancel a booking","tags":["Bookings"],"security":[{"bearerAuth":["write:bookings"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"reason","in":"query","schema":{"type":"string","maxLength":500}}],"responses":{"200":{"description":"Canceled (idempotent)."},"404":{"description":"Booking not found."},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/leads":{"get":{"summary":"List captured leads on the authenticated user's event types","tags":["Leads"],"security":[{"bearerAuth":["read:leads"]}],"parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["new","contacted","qualified","lost"]}},{"name":"booked","in":"query","description":"Filter on whether the lead converted into a booking.","schema":{"type":"boolean"}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":100}}],"responses":{"200":{"description":"Paginated leads, newest first.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Lead"}},"nextCursor":{"type":"string","nullable":true}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/contacts":{"get":{"summary":"List contacts (clients + leads merged by email)","tags":["Contacts"],"security":[{"bearerAuth":["read:contacts"]}],"parameters":[{"name":"kind","in":"query","description":"Filter to clients or leads only.","schema":{"type":"string","enum":["client","lead"]}},{"name":"q","in":"query","description":"Case-insensitive substring match on name or email.","schema":{"type":"string"}},{"name":"offset","in":"query","description":"Contacts are derived; page with offset/limit.","schema":{"type":"integer","default":0}},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":200}}],"responses":{"200":{"description":"Paginated contacts, most-recent activity first.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Contact"}},"total":{"type":"integer","description":"Total contacts after filters."},"nextOffset":{"type":"integer","nullable":true}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"}}}}}}