{"openapi":"3.1.0","info":{"title":"topcal API","version":"0.1.0","description":"Agent-native scheduling. Every operation is reachable via REST (this spec) and via MCP (`/api/mcp`). Both surfaces share the same Zod schemas, so a tool that works in one works in the other.\n\nBrowse interactive docs at `/docs`. All errors use a stable envelope: `{ error: { code, message, details? } }`. Authenticated JSON, and any response that carries a key or email code, is `Cache-Control: no-store`. 429s include `Retry-After` and `RateLimit-*` when the limiter exposes a window. List or revoke keys with `GET`/`DELETE /workspace/api-keys`. The HTTP API covers signup and booking; the CLI is optional."},"servers":[{"url":"https://app.topcal.ai/api/v1","description":"v1"}],"security":[{"ApiKey":[]}],"components":{"securitySchemes":{"ApiKey":{"type":"http","scheme":"bearer","bearerFormat":"topcal-api-key","description":"Workspace API key. Format: `topcal_live_<32-char-secret>` (keys issued before October 2026 start with `tofu_` and still work)."},"AgentIntent":{"type":"apiKey","in":"header","name":"X-Topcal-Agent-Intent","description":"Short-lived delegated JWT bound to a verified `agent_principal` and the API key used to verify it. Send the JWT in X-Topcal-Agent-Intent AND the original API key in Authorization: Bearer for delegated operations."}},"schemas":{"ApiError":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable machine-readable error code"},"message":{"type":"string","description":"Human-readable error message"},"details":{}},"required":["code","message"]}},"required":["error"]},"HealthResponse":{"type":"object","properties":{"status":{"type":"string","enum":["ok"]},"name":{"type":"string","enum":["topcal"]},"version":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"transports":{"type":"object","properties":{"rest":{"type":"string","description":"Path to the REST API"},"mcp":{"type":"string","description":"Path to the Model Context Protocol endpoint"},"openapi":{"type":"string","description":"Path to the OpenAPI 3.1 spec JSON"}},"required":["rest","mcp","openapi"]}},"required":["status","name","version","timestamp","transports"]},"CliAuthRegisterResponse":{"type":"object","properties":{"deviceCode":{"type":"string"},"userCode":{"type":"string"},"verificationUrl":{"type":"string","format":"uri"},"expiresIn":{"type":"integer","exclusiveMinimum":0},"interval":{"type":"integer","exclusiveMinimum":0}},"required":["deviceCode","userCode","verificationUrl","expiresIn","interval"]},"CliAuthRegisterRequest":{"type":"object","properties":{"agentName":{"type":"string","minLength":1,"maxLength":80},"clientName":{"type":"string","minLength":1,"maxLength":80}}},"CliAuthPollResponse":{"type":"object","properties":{"status":{"type":"string","enum":["authorization_pending","approved","expired","denied","slow_down"]},"apiKey":{"type":"string"},"apiUrl":{"type":"string","format":"uri"},"workspace":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"]},"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"}},"required":["id","email"]}},"required":["status"]},"CliListCalendarsResponse":{"type":"object","properties":{"calendars":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"provider":{"type":"string"},"email":{"type":"string"},"seatStatus":{"type":"string"},"organizationId":{"type":["string","null"],"format":"uuid"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","provider","email","seatStatus","organizationId","createdAt"]}}},"required":["calendars"]},"CliConnectCalendarResponse":{"type":"object","properties":{"installUrl":{"type":"string","format":"uri"},"expiresAt":{"type":"string","format":"date-time"},"targetUser":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"}},"required":["id","email"]},"instructions":{"type":"string"},"viaAgentSeat":{"type":"boolean","description":"True when a bot minted this link for a human member."}},"required":["installUrl","expiresAt","targetUser","instructions","viaAgentSeat"]},"CliConnectCalendarRequest":{"type":"object","properties":{"provider":{"type":"string","enum":["google","microsoft"]},"redirectAfter":{"type":"string","maxLength":512,"pattern":"^\\/"},"forEmail":{"type":"string","format":"email","description":"Agent-seat keys only: the workspace member whose calendar to connect. Defaults to the person who approved the seat."}},"required":["provider"]},"NativeAuthEmailStartResponse":{"type":"object","properties":{"challengeId":{"type":"string","format":"uuid"},"expiresIn":{"type":"integer","exclusiveMinimum":0},"resendAfter":{"type":"integer","exclusiveMinimum":0}},"required":["challengeId","expiresIn","resendAfter"]},"NativeAuthEmailStartRequest":{"type":"object","properties":{"email":{"type":"string","maxLength":254,"format":"email"},"clientName":{"type":"string","minLength":1,"maxLength":80,"description":"App name, e.g. \"topcal for iPhone\". Same meaning as /cli/auth/register."},"agentName":{"type":"string","minLength":1,"maxLength":80,"description":"Agent/device label, e.g. \"topcal for iPhone\". Names the minted key."},"prospectEmail":{"type":"string","maxLength":254,"format":"email","description":"Human operator email. Required when `email` is an agent inbox (e.g. mail.grokbot.com) and that inbox does not yet own a workspace."}},"required":["email"]},"NativeAuthVerifyResponse":{"anyOf":[{"$ref":"#/components/schemas/NativeAuthResult"},{"$ref":"#/components/schemas/NativeAuthPendingClaim"}]},"NativeAuthResult":{"type":"object","properties":{"apiKey":{"type":"string","description":"Workspace API key (workspace.act). Returned once."},"apiUrl":{"type":"string","format":"uri"},"workspace":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"]},"user":{"type":"object","properties":{"email":{"type":"string","format":"email"},"name":{"type":["string","null"]}},"required":["email","name"]},"isNewAccount":{"type":"boolean"}},"required":["apiKey","apiUrl","workspace","user","isNewAccount"]},"NativeAuthPendingClaim":{"type":"object","properties":{"status":{"type":"string","enum":["pending_claim"]},"pollToken":{"type":"string","description":"One-time token for POST /native/auth/claim/poll. Returned once."},"claimSentTo":{"type":"string","format":"email"},"expiresIn":{"type":"integer","exclusiveMinimum":0},"instructions":{"type":"string"}},"required":["status","pollToken","claimSentTo","expiresIn","instructions"]},"NativeAuthEmailVerifyRequest":{"type":"object","properties":{"challengeId":{"type":"string","format":"uuid"},"code":{"type":"string","minLength":1,"maxLength":16},"clientName":{"type":"string","minLength":1,"maxLength":80,"description":"App name, e.g. \"topcal for iPhone\". Same meaning as /cli/auth/register."},"agentName":{"type":"string","minLength":1,"maxLength":80,"description":"Agent/device label, e.g. \"topcal for iPhone\". Names the minted key."},"prospectEmail":{"type":"string","maxLength":254,"format":"email","description":"Human operator email. Required when `email` is an agent inbox (e.g. mail.grokbot.com) and that inbox does not yet own a workspace."}},"required":["challengeId","code"]},"NativeAuthClaimPollResponse":{"anyOf":[{"$ref":"#/components/schemas/NativeAuthClaimPollPending"},{"$ref":"#/components/schemas/NativeAuthClaimPollClaimed"}]},"NativeAuthClaimPollPending":{"type":"object","properties":{"status":{"type":"string","enum":["pending_claim"]},"claimSentTo":{"type":"string","format":"email"},"expiresIn":{"type":"integer","exclusiveMinimum":0}},"required":["status","claimSentTo","expiresIn"]},"NativeAuthClaimPollClaimed":{"allOf":[{"$ref":"#/components/schemas/NativeAuthResult"},{"type":"object","properties":{"status":{"type":"string","enum":["claimed"]}},"required":["status"]}]},"NativeAuthClaimPollRequest":{"type":"object","properties":{"pollToken":{"type":"string","minLength":16,"maxLength":256}},"required":["pollToken"]},"NativeAuthAppleRequest":{"type":"object","properties":{"identityToken":{"type":"string","minLength":1,"maxLength":8192},"rawNonce":{"type":"string","minLength":1,"maxLength":512},"fullName":{"type":["object","null"],"properties":{"givenName":{"type":["string","null"],"maxLength":100},"familyName":{"type":["string","null"],"maxLength":100}}},"clientName":{"type":"string","minLength":1,"maxLength":80,"description":"App name, e.g. \"topcal for iPhone\". Same meaning as /cli/auth/register."},"agentName":{"type":"string","minLength":1,"maxLength":80,"description":"Agent/device label, e.g. \"topcal for iPhone\". Names the minted key."},"prospectEmail":{"type":"string","maxLength":254,"format":"email","description":"Human operator email. Required when `email` is an agent inbox (e.g. mail.grokbot.com) and that inbox does not yet own a workspace."}},"required":["identityToken","rawNonce"]},"NativeAuthPasskeyOptionsResponse":{"type":"object","properties":{"challengeId":{"type":"string"},"publicKey":{"type":"object","properties":{"challenge":{"type":"string","description":"base64url"},"timeout":{"type":"integer","exclusiveMinimum":0},"rpId":{"type":"string"},"allowCredentials":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["public-key"]},"id":{"type":"string"},"transports":{"type":"array","items":{"type":"string"}}},"required":["type","id"]}},"userVerification":{"type":"string","enum":["required"]}},"required":["challenge","rpId","allowCredentials","userVerification"],"description":"PublicKeyCredentialRequestOptionsJSON"}},"required":["challengeId","publicKey"]},"NativeAuthPasskeyOptionsRequest":{"type":"object","properties":{"clientName":{"type":"string","minLength":1,"maxLength":80,"description":"App name, e.g. \"topcal for iPhone\". Same meaning as /cli/auth/register."},"agentName":{"type":"string","minLength":1,"maxLength":80,"description":"Agent/device label, e.g. \"topcal for iPhone\". Names the minted key."},"prospectEmail":{"type":"string","maxLength":254,"format":"email","description":"Human operator email. Required when `email` is an agent inbox (e.g. mail.grokbot.com) and that inbox does not yet own a workspace."}}},"NativeAuthPasskeyVerifyRequest":{"type":"object","properties":{"challengeId":{"type":"string","minLength":1,"maxLength":200},"credential":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":16384,"pattern":"^[A-Za-z0-9_-]+={0,2}$"},"rawId":{"type":"string","minLength":1,"maxLength":16384,"pattern":"^[A-Za-z0-9_-]+={0,2}$"},"type":{"type":"string","enum":["public-key"]},"response":{"type":"object","properties":{"clientDataJSON":{"type":"string","minLength":1,"maxLength":16384,"pattern":"^[A-Za-z0-9_-]+={0,2}$"},"authenticatorData":{"type":"string","minLength":1,"maxLength":16384,"pattern":"^[A-Za-z0-9_-]+={0,2}$"},"signature":{"type":"string","minLength":1,"maxLength":16384,"pattern":"^[A-Za-z0-9_-]+={0,2}$"},"userHandle":{"type":["string","null"],"minLength":1,"maxLength":16384,"pattern":"^[A-Za-z0-9_-]+={0,2}$"}},"required":["clientDataJSON","authenticatorData","signature"]}},"required":["id","rawId","type","response"]},"clientName":{"type":"string","minLength":1,"maxLength":80,"description":"App name, e.g. \"topcal for iPhone\". Same meaning as /cli/auth/register."},"agentName":{"type":"string","minLength":1,"maxLength":80,"description":"Agent/device label, e.g. \"topcal for iPhone\". Names the minted key."},"prospectEmail":{"type":"string","maxLength":254,"format":"email","description":"Human operator email. Required when `email` is an agent inbox (e.g. mail.grokbot.com) and that inbox does not yet own a workspace."}},"required":["challengeId","credential"]},"RegisterAgentIdentityResponse":{"type":"object","properties":{"principalId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending"]},"verificationExpiresAt":{"type":"string","format":"date-time"},"instructions":{"type":"string"}},"required":["principalId","status","verificationExpiresAt","instructions"]},"RegisterAgentIdentityRequest":{"type":"object","properties":{"prospectEmail":{"type":"string","format":"email"},"prospectName":{"type":"string","minLength":1,"maxLength":120},"prospectCompany":{"type":"string","minLength":1,"maxLength":120},"agentLabel":{"type":"string","minLength":1,"maxLength":160},"metadata":{"type":"object","additionalProperties":{}}},"required":["prospectEmail","agentLabel"]},"VerifyAgentIdentityResponse":{"type":"object","properties":{"principalId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["verified"]},"intentToken":{"type":"string"},"expiresAt":{"type":"string","format":"date-time"},"scopes":{"type":"array","items":{"type":"string","enum":["agent.identity.read","agent.identity.revoke","agent.user.signup","agent.workspace.create","agent.workspace.invite","agent.billing.checkout","agent.booking.read","agent.booking.write","agent.calendar.connect"]}}},"required":["principalId","status","intentToken","expiresAt","scopes"]},"VerifyAgentIdentityRequest":{"type":"object","properties":{"code":{"type":"string","pattern":"^\\d{6}$"},"scopes":{"type":"array","items":{"type":"string","enum":["agent.identity.read","agent.identity.revoke","agent.user.signup","agent.workspace.create","agent.workspace.invite","agent.billing.checkout","agent.booking.read","agent.booking.write","agent.calendar.connect"]},"minItems":1,"maxItems":9}},"required":["code","scopes"]},"RevokeAgentIdentityResponse":{"type":"object","properties":{"principalId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["revoked"]},"revokedAt":{"type":"string","format":"date-time"}},"required":["principalId","status","revokedAt"]},"SignupAgentUserResponse":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"name":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","email","name","createdAt"]},"workspaces":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"role":{"type":"string","enum":["owner","admin","manager","member","billing_only"]}},"required":["id","slug","name","role"]}},"created":{"type":"boolean"},"claimAccountUrl":{"type":"string","format":"uri"}},"required":["user","workspaces","created","claimAccountUrl"]},"SignupAgentUserRequest":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"timezone":{"type":"string","minLength":1,"maxLength":80}}},"AgentConnectCalendarResponse":{"type":"object","properties":{"installUrl":{"type":"string","format":"uri"},"expiresAt":{"type":"string","format":"date-time"},"targetUser":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"}},"required":["id","email"]},"instructions":{"type":"string"}},"required":["installUrl","expiresAt","targetUser","instructions"]},"AgentConnectCalendarRequest":{"type":"object","properties":{"provider":{"type":"string","enum":["google","microsoft"]},"redirectAfter":{"type":"string","maxLength":512,"pattern":"^\\/"}},"required":["provider"]},"StartCheckoutResponse":{"type":"object","properties":{"intentId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending"]},"url":{"type":"string","format":"uri"},"expiresAt":{"type":"string","format":"date-time"},"plan":{"type":"string","enum":["solo","plus","pro"]},"interval":{"type":"string","enum":["monthly","annual"]},"quantity":{"type":"integer","minimum":1}},"required":["intentId","status","url","expiresAt","plan","interval","quantity"]},"StartCheckoutRequest":{"type":"object","properties":{"plan":{"type":"string","enum":["starter","plus","growth","solo","pro"]},"interval":{"type":"string","enum":["monthly","annual"],"default":"monthly"},"quantity":{"type":"integer","minimum":1,"maximum":20,"default":1},"customerEmail":{"type":"string","format":"email"},"successUrl":{"type":"string","format":"uri"},"cancelUrl":{"type":"string","format":"uri"},"metadata":{"type":"object","additionalProperties":{"type":"string"}}},"required":["plan"]},"CheckoutIntentResponse":{"type":"object","properties":{"intentId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending","completed","expired","canceled"]},"requestedPriceId":{"type":"string"},"completedAt":{"type":["string","null"],"format":"date-time"},"expiresAt":{"type":"string","format":"date-time"},"sessionId":{"type":"string"}},"required":["intentId","status","requestedPriceId","completedAt","expiresAt","sessionId"]},"StartEnrichmentCheckoutResponse":{"type":"object","properties":{"intentId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending"]},"url":{"type":"string","format":"uri"},"expiresAt":{"type":"string","format":"date-time"},"catalogId":{"type":"string","enum":["enrichment_starter","enrichment_growth","enrichment_scale","enrichment_pack_50","enrichment_pack_200","enrichment_pack_500"]}},"required":["intentId","status","url","expiresAt","catalogId"]},"StartEnrichmentCheckoutRequest":{"type":"object","properties":{"catalogId":{"type":"string","enum":["enrichment_starter","enrichment_growth","enrichment_scale","enrichment_pack_50","enrichment_pack_200","enrichment_pack_500"]},"customerEmail":{"type":"string","format":"email"},"successUrl":{"type":"string","format":"uri"},"cancelUrl":{"type":"string","format":"uri"},"metadata":{"type":"object","additionalProperties":{"type":"string"}}},"required":["catalogId"]},"AgentCreateBookingResponse":{"type":"object","properties":{"booking":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"eventTypeId":{"type":"string","format":"uuid"},"startAt":{"type":"string","format":"date-time"},"endAt":{"type":"string","format":"date-time"},"status":{"type":"string","enum":["pending_confirmation","confirmed","canceled","rescheduled","no_show","completed"]},"joinUrl":{"type":"string","format":"uri"},"htmlLink":{"type":"string","format":"uri"}},"required":["id","eventTypeId","startAt","endAt","status"]},"message":{"type":"string"}},"required":["booking","message"]},"AgentCreateBookingRequest":{"type":"object","properties":{"eventTypeId":{"type":"string","format":"uuid"},"startAt":{"type":"string","format":"date-time"},"invitee":{"type":"object","properties":{"email":{"type":"string","format":"email"},"name":{"type":"string","minLength":1,"maxLength":120},"timezone":{"type":"string","minLength":1,"maxLength":80}},"required":["email","timezone"]},"customFields":{"type":"object","additionalProperties":{}},"guests":{"type":"array","items":{"type":"string","maxLength":254},"maxItems":10,"description":"Extra emails to add to the calendar invite."},"idempotencyKey":{"type":"string","minLength":8,"maxLength":128}},"required":["eventTypeId","startAt","invitee"]},"BookingDetailResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"startAt":{"type":"string","format":"date-time"},"endAt":{"type":"string","format":"date-time"},"status":{"type":"string"},"timezone":{"type":"string"},"locationType":{"type":"string"},"source":{"type":"string"},"joinUrl":{"type":["string","null"]},"eventType":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":["string","null"]},"slug":{"type":["string","null"]}},"required":["id","name","slug"]},"invitee":{"type":"object","properties":{"name":{"type":["string","null"]},"email":{"type":["string","null"]},"timezone":{"type":["string","null"]}},"required":["name","email","timezone"]},"hostNotes":{"type":["string","null"]},"formAnswers":{"type":"array","items":{"$ref":"#/components/schemas/BookingFormAnswerEntry"}},"formAnswersByKey":{"type":"object","additionalProperties":{}}},"required":["id","startAt","endAt","status","timezone","locationType","source","joinUrl","eventType","invitee","hostNotes","formAnswers","formAnswersByKey"]},"BookingFormAnswerEntry":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"value":{"description":"Stored answer (option.value for selects)."},"display":{"type":"string","description":"Human-readable answer (option.label for selects)."}},"required":["key","label","display"]},"BookingEnrichmentResponse":{"type":"object","properties":{"bookingId":{"type":"string","format":"uuid"},"status":{"type":"string"},"emailClass":{"type":["string","null"]},"domain":{"type":["string","null"]},"creditsCharged":{"type":"integer"},"companyFacts":{"type":["object","null"],"additionalProperties":{}},"personFacts":{"type":["object","null"],"additionalProperties":{}},"conversationSignals":{"type":["object","null"],"additionalProperties":{}},"brief":{"type":["object","null"],"additionalProperties":{}},"score":{"type":["object","null"],"additionalProperties":{}},"providerBreakdown":{"type":["object","null"],"additionalProperties":{}},"error":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["bookingId","status","emailClass","domain","creditsCharged","companyFacts","personFacts","conversationSignals","brief","score","providerBreakdown","error","createdAt","updatedAt"]},"HostPrepPack":{"type":"object","properties":{"bookingId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["none","pending","running","succeeded","failed","degraded"]},"templateHint":{"type":"string","enum":["sales","partnership","hiring","cs","general"]},"generatedAt":{"type":"string","format":"date-time"},"markdown":{"type":"string"},"guest":{"type":"object","properties":{"name":{"type":"string"},"email":{"type":"string"},"title":{"type":"string"},"linkedin":{"type":"string"}},"required":["name","email"]},"company":{"type":"object","properties":{"domain":{"type":"string"},"oneLiner":{"type":"string"},"sizeSignal":{"type":"string"},"footprint":{"type":"string"}},"required":["domain","oneLiner"]},"whyMeeting":{"type":"object","properties":{"eventType":{"type":"string"},"bookingAnswers":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"value":{"type":"string"}},"required":["label","value"]}},"hostNotes":{"type":"string"}},"required":["eventType","bookingAnswers"]},"locks":{"type":"object","properties":{"brandSpeakFrom":{"type":"array","items":{"type":"string"}},"doNotSay":{"type":"array","items":{"type":"string"}},"softQualifyOnly":{"type":"boolean"}},"required":["brandSpeakFrom","doNotSay"]},"questions":{"type":"array","items":{"type":"object","properties":{"n":{"type":"integer","minimum":1},"text":{"type":"string","minLength":1},"intent":{"type":"string","enum":["process_walkthrough","where_it_breaks","missing_early","narrow_pilot","output_users_format","success_number","data_sources","approval_owners","continue_if_hit","contextual_question"]}},"required":["n","text","intent"]}},"closer":{"type":"string"},"provenance":{"type":"array","items":{"type":"object","properties":{"claim":{"type":"string","minLength":1},"tag":{"type":"string","enum":["estimate","source","host","guest"]},"sourceUrl":{"type":"string","format":"uri"}},"required":["claim","tag"]}},"enrichmentRecordId":{"type":"string","format":"uuid"},"modelMeta":{"type":"object","properties":{"promptVersion":{"type":"string"},"generator":{"type":"string","enum":["deterministic"]},"questionsSource":{"type":"string","enum":["research","starter","stale_research"]}},"required":["promptVersion","generator"]},"sourceFingerprint":{"type":"string"}},"required":["bookingId","status","generatedAt","markdown","guest","company","whyMeeting","locks","questions","closer","provenance","modelMeta","sourceFingerprint"]},"AgentRescheduleResponse":{"type":"object","properties":{"booking":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"startAt":{"type":"string","format":"date-time"},"endAt":{"type":"string","format":"date-time"},"status":{"type":"string"},"joinUrl":{"type":"string","format":"uri"},"htmlLink":{"type":"string","format":"uri"}},"required":["id","startAt","endAt","status"]},"message":{"type":"string"}},"required":["booking","message"]},"AgentRescheduleRequest":{"type":"object","properties":{"startAt":{"type":"string","format":"date-time","description":"New slot start, ISO 8601 UTC"}},"required":["startAt"]},"AgentCancelResponse":{"type":"object","properties":{"booking":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"}},"required":["id","status"]},"message":{"type":"string"}},"required":["booking","message"]},"AgentCancelRequest":{"type":"object","properties":{"reason":{"type":"string","maxLength":500}}},"AgentProposeSlotsResponse":{"type":"object","properties":{"eventTypeId":{"type":"string","format":"uuid"},"slots":{"type":"array","items":{"type":"object","properties":{"startUtc":{"type":"string","format":"date-time"},"endUtc":{"type":"string","format":"date-time"}},"required":["startUtc","endUtc"]}},"count":{"type":"integer"}},"required":["eventTypeId","slots","count"]},"AgentProposeSlotsRequest":{"type":"object","properties":{"eventTypeId":{"type":"string","format":"uuid"},"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"},"limit":{"type":"integer","minimum":1,"maximum":50,"default":8}},"required":["eventTypeId"]},"PublicEventTypesResponse":{"type":"object","properties":{"calendar":{"type":"object","properties":{"organization":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"}},"required":["slug","name"]},"owner":{"type":"object","properties":{"username":{"type":"string"}},"required":["username"]},"hostTimezone":{"type":["string","null"]}},"required":["organization","owner","hostTimezone"]},"invitee":{"type":"object","properties":{"fields":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"Stable identifier. Pass answers keyed by this exact value."},"type":{"type":"string","description":"Field input type (e.g. short_text, single_select, boolean)."},"label":{"type":"string","description":"Human-facing question label."},"required":{"type":"boolean","description":"Whether an answer is required when the field is visible."},"helpText":{"type":"string","description":"Guidance for the answerer. Doubles as the agent-facing field description."},"config":{"description":"Type-specific config (e.g. `options` for selects)."},"conditionalLogic":{"description":"When present, the field is only required if these prior answers match."}},"required":["key","type","label","required"]},"description":"Always collect these on GET .../otp (as query params). Custom intake lives in `eventType.form`."}},"required":["fields"]},"eventTypes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"durationMinutes":{"type":"integer"},"locationType":{"type":"string"},"maxFutureDays":{"type":"integer"},"form":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"definition":{"$ref":"#/components/schemas/FormDefinition"},"requiredFieldKeys":{"type":"array","items":{"type":"string"}}},"required":["id","definition","requiredFieldKeys"]}},"required":["id","slug","name","description","durationMinutes","locationType","maxFutureDays","form"]}}},"required":["calendar","invitee","eventTypes"]},"FormDefinition":{"type":["object","null"],"properties":{"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"fields":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"Stable identifier. Pass answers keyed by this exact value."},"type":{"type":"string","description":"Field input type (e.g. short_text, single_select, boolean)."},"label":{"type":"string","description":"Human-facing question label."},"required":{"type":"boolean","description":"Whether an answer is required when the field is visible."},"helpText":{"type":"string","description":"Guidance for the answerer. Doubles as the agent-facing field description."},"config":{"description":"Type-specific config (e.g. `options` for selects)."},"conditionalLogic":{"description":"When present, the field is only required if these prior answers match."}},"required":["key","type","label","required"]}}},"required":["slug","name","fields"]},"PublicSlotsResponse":{"type":"object","properties":{"calendar":{"type":"object","properties":{"organization":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"}},"required":["slug","name"]},"owner":{"type":"object","properties":{"username":{"type":"string"}},"required":["username"]},"hostTimezone":{"type":["string","null"],"description":"Host IANA timezone — weekly hours live in availability.hostSchedule."}},"required":["organization","owner","hostTimezone"]},"eventType":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"durationMinutes":{"type":"integer"},"locationType":{"type":"string"},"maxFutureDays":{"type":"integer"},"form":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"definition":{"$ref":"#/components/schemas/FormDefinition"},"requiredFieldKeys":{"type":"array","items":{"type":"string"}}},"required":["id","definition","requiredFieldKeys"]}},"required":["id","slug","name","durationMinutes","locationType","maxFutureDays","form"]},"invitee":{"type":"object","properties":{"fields":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"Stable identifier. Pass answers keyed by this exact value."},"type":{"type":"string","description":"Field input type (e.g. short_text, single_select, boolean)."},"label":{"type":"string","description":"Human-facing question label."},"required":{"type":"boolean","description":"Whether an answer is required when the field is visible."},"helpText":{"type":"string","description":"Guidance for the answerer. Doubles as the agent-facing field description."},"config":{"description":"Type-specific config (e.g. `options` for selects)."},"conditionalLogic":{"description":"When present, the field is only required if these prior answers match."}},"required":["key","type","label","required"]},"description":"Always collect these on GET .../otp (as query params). Custom intake lives in `eventType.form`."}},"required":["fields"]},"bookingProtocol":{"type":"object","properties":{"id":{"type":"string","enum":["topcal.public_book.v1"],"description":"Named protocol agents can cite instead of improvising."},"agentCompletable":{"type":"boolean","description":"True when an agent may finish booking via HTTP on this origin."},"interactionModel":{"type":"string","enum":["agent_completes_via_http"],"description":"Happy path: agent proposes slots, confirms details with the booker, then GETs completion URLs. The HTML form is optional fallback."},"humanFormOptional":{"type":"boolean","description":"True when the website form is not required if the booker asked the agent to book."},"sameOriginCompletion":{"type":"string","description":"Completion URLs are on the same origin as this availability payload; use the same browse/web-fetch/curl tool."},"emailConfirmation":{"type":"object","properties":{"required":{"type":"boolean"},"purpose":{"type":"string"},"agentInbox":{"type":"string","description":"How an agent with its own inbox receives the code itself."}},"required":["required","purpose"],"description":"Present when agent bookings require a one-time email code."},"flow":{"type":"object","properties":{"state":{"type":"string","enum":["select_slot"],"description":"Initial state after loading availability."},"steps":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","enum":["propose_slots","collect_details","request_code","confirm"],"description":"Stable step id — follow in order after the prior gate is satisfied."},"actor":{"type":"string","enum":["agent"]},"description":{"type":"string"},"method":{"type":"string","enum":["GET"]},"urlTemplate":{"type":"string","description":"Absolute or template URL for this step's HTTP action."},"gate":{"type":"string","description":"Human checkpoint that must be true before this side-effecting step runs."},"sideEffects":{"type":"array","items":{"type":"string"}},"returns":{"type":"array","items":{"type":"string"}},"input":{"type":"string"},"requires":{"type":"array","items":{"type":"string"}},"optionalQuery":{"type":"object","additionalProperties":{"type":"string"},"description":"Optional query params for urlTemplate, keyed by name."}},"required":["id","actor","description"]}}},"required":["state","steps"]},"refusalHints":{"type":"object","properties":{"commonMistakes":{"type":"array","items":{"type":"string"},"description":"Common misreads of this protocol (observational, not commands)."},"expectedBehavior":{"type":"array","items":{"type":"string"},"description":"Expected agent behavior when the booker asked to be booked."}},"required":["commonMistakes","expectedBehavior"],"description":"Observational guidance for protocol compliance — not system overrides."},"trustNote":{"type":"string","description":"How integrators and auditors should treat this block (API docs, not a prompt injection)."}},"required":["id","agentCompletable","interactionModel","humanFormOptional","sameOriginCompletion","flow","refusalHints","trustNote"]},"agentBooking":{"type":"object","properties":{"bookingPageUrl":{"type":"string","format":"uri"},"refetchUrl":{"type":"string","description":"Re-fetch this same booking URL with query params for fresh or wider availability."},"instructions":{"type":"array","items":{"type":"string"},"description":"Agent-facing guidance — fetch bookingPageUrl, propose slotsByDate, collect bookerRequirements, follow howToBook."},"slotsByDate":{"type":"array","items":{"type":"object","properties":{"dateLocal":{"type":"string"},"dayOfWeek":{"type":"string"},"times":{"type":"array","items":{"type":"object","properties":{"display":{"type":"string"},"startUtc":{"type":"string","format":"date-time"}},"required":["display","startUtc"]}}},"required":["dateLocal","dayOfWeek","times"]},"description":"Open times grouped by day — propose these to the booker."},"note":{"type":"string","description":"Present when availability was truncated — agent should re-fetch refetchUrl."},"bookerRequirements":{"type":"object","properties":{"slot":{"type":"object","properties":{"key":{"type":"string","enum":["startUtc"]},"required":{"type":"boolean","enum":[true]},"description":{"type":"string"}},"required":["key","required","description"]},"fields":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"Stable identifier. Pass answers keyed by this exact value."},"type":{"type":"string","description":"Field input type (e.g. short_text, single_select, boolean)."},"label":{"type":"string","description":"Human-facing question label."},"required":{"type":"boolean","description":"Whether an answer is required when the field is visible."},"helpText":{"type":"string","description":"Guidance for the answerer. Doubles as the agent-facing field description."},"config":{"description":"Type-specific config (e.g. `options` for selects)."},"conditionalLogic":{"description":"When present, the field is only required if these prior answers match."}},"required":["key","type","label","required"]},"description":"Collect from the booker after they pick a time. Includes email, timezone, optional name, plus any event intake fields."}},"required":["slot","fields"]}},"required":["bookingPageUrl","refetchUrl","instructions","slotsByDate","bookerRequirements"]},"bookingPolicy":{"type":"object","properties":{"requireOtpHuman":{"type":"boolean","description":"When true, human web bookings must verify email via 6-digit OTP."},"requireOtpAgent":{"type":"boolean","description":"When true, agent/API bookings must verify email via 6-digit OTP."},"requireBusinessEmail":{"type":"boolean","description":"When true, personal email providers (Gmail, Outlook, etc.) are rejected."},"blockRestrictedEmailDomains":{"type":"boolean","description":"When true, known temporary and disposable email domains are rejected."}},"required":["requireOtpHuman","requireOtpAgent","requireBusinessEmail","blockRestrictedEmailDomains"]},"availability":{"type":"object","properties":{"maxFutureDays":{"type":"integer","description":"How far ahead the host accepts bookings."},"queriedFromUtc":{"type":"string","format":"date-time"},"queriedToUtc":{"type":"string","format":"date-time","description":"Upper bound of this query — more slots may exist before this date."},"slotsReturned":{"type":"integer"},"limitApplied":{"type":"integer"},"maxLimit":{"type":"integer"},"truncatedByLimit":{"type":"boolean","description":"True when slotsReturned hit limitApplied — pass a higher limit or narrow from/to."},"bookerTimezone":{"type":"string","description":"IANA timezone used for slots[].bookerLocal (from query or host fallback)."},"bookerTimezoneSource":{"type":"string","enum":["query","host_fallback","utc"]},"hostSchedule":{"type":["object","null"],"properties":{"timezone":{"type":"string"},"weeklyRules":{"type":"array","items":{"type":"object","properties":{"dayOfWeek":{"type":"integer","minimum":0,"maximum":6},"dayName":{"type":"string"},"startTime":{"type":"string","description":"HH:mm in host schedule timezone"},"endTime":{"type":"string"}},"required":["dayOfWeek","dayName","startTime","endTime"]}},"summary":{"type":"string","description":"Human-readable weekly hours, e.g. Mon–Fri · 9:00 AM – 5:00 PM"}},"required":["timezone","weeklyRules","summary"],"description":"Host-configured weekly hours; slots never fall outside these windows."},"firstSlotStartUtc":{"type":["string","null"],"format":"date-time"},"lastSlotStartUtc":{"type":["string","null"],"format":"date-time"},"nextAvailableStartUtc":{"type":["string","null"],"format":"date-time","description":"Same as firstSlotStartUtc when slots are non-empty."},"datesInPayload":{"type":"array","items":{"type":"string"},"description":"Local dates (YYYY-MM-DD, booker timezone) covered by slots[] / slotsByDate."},"fromDate":{"type":["string","null"],"description":"When the query was narrowed with fromDate=YYYY-MM-DD."},"toDate":{"type":["string","null"],"description":"When the query was narrowed with toDate=YYYY-MM-DD."}},"required":["maxFutureDays","queriedFromUtc","queriedToUtc","slotsReturned","limitApplied","maxLimit","truncatedByLimit","bookerTimezone","bookerTimezoneSource","hostSchedule","firstSlotStartUtc","lastSlotStartUtc","nextAvailableStartUtc","datesInPayload","fromDate","toDate"]},"slots":{"type":"array","items":{"type":"object","properties":{"startUtc":{"type":"string","format":"date-time"},"endUtc":{"type":"string","format":"date-time"},"bookerLocal":{"type":"object","properties":{"timezone":{"type":"string"},"dateLocal":{"type":"string","description":"YYYY-MM-DD in booker's timezone"},"dayOfWeek":{"type":"string"},"startLocal":{"type":"string"},"endLocal":{"type":"string"},"display":{"type":"string","description":"Ready-to-show time range for the booker, in their timezone"}},"required":["timezone","dateLocal","dayOfWeek","startLocal","endLocal","display"]}},"required":["startUtc","endUtc","bookerLocal"]}},"emptyReason":{"type":"string","enum":["workspace_locked","no_schedule","no_rules","no_calendar","no_slots"]},"howToBook":{"type":"object","properties":{"steps":{"type":"array","items":{"type":"string"}},"requestCodeUrl":{"type":"string"},"confirmResponse":{"type":"object","properties":{"booking":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"startAt":{"type":"string","format":"date-time"},"endAt":{"type":"string","format":"date-time"},"status":{"type":"string"},"joinUrl":{"type":"string","format":"uri","description":"Video/meeting link when the host uses a virtual location."}},"required":["id","startAt","endAt","status"]},"message":{"type":"string"}},"required":["booking","message"],"description":"Shape returned by GET .../confirm on success."}},"required":["steps","requestCodeUrl","confirmResponse"]}},"required":["calendar","eventType","invitee","bookingProtocol","agentBooking","bookingPolicy","availability","slots","howToBook"]},"PublicBookingOtpResponse":{"type":"object","properties":{"status":{"type":"string","enum":["otp_sent"]},"email":{"type":"string","format":"email"},"codeSentTo":{"type":"string","format":"email","description":"Inbox the code went to — `agentEmail` when given, else `email`."},"notice":{"type":"string"},"expiresInMinutes":{"type":"integer"},"codeExpiresInSeconds":{"type":"integer","description":"Seconds until the emailed code expires."},"message":{"type":"string"}},"required":["status","email","codeSentTo","expiresInMinutes","codeExpiresInSeconds","message"]},"PublicBookingOtpRequest":{"type":"object","properties":{"email":{"type":"string","format":"email","description":"The attendee's email — the calendar invite goes here."},"name":{"type":"string","minLength":1,"maxLength":120},"agentEmail":{"type":"string","format":"email","description":"Your own inbox, when you are an AI agent booking for the human at `email`. The code is sent here instead of to the human; the calendar invite still goes to `email`."}},"required":["email"]},"PublicBookingOtpGetResponse":{"type":"object","properties":{"status":{"type":"string","enum":["otp_sent","confirmation_ready"]},"verificationRequired":{"type":"boolean","description":"When false, GET confirmUrl directly — no emailed code."},"email":{"type":"string","format":"email"},"codeSentTo":{"type":"string","format":"email","description":"Inbox the code went to — `agentEmail` when given, else `email`."},"notice":{"type":"string"},"expiresInMinutes":{"type":"integer"},"codeExpiresInSeconds":{"type":"integer","description":"Seconds until the emailed code expires (0 when verification not required)."},"confirmUrl":{"type":"string"},"next":{"type":"string"}},"required":["status","verificationRequired","email","expiresInMinutes","codeExpiresInSeconds","confirmUrl","next"]},"PublicBookResponse":{"type":"object","properties":{"booking":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"startAt":{"type":"string","format":"date-time"},"endAt":{"type":"string","format":"date-time"},"status":{"type":"string"},"joinUrl":{"type":"string","format":"uri"}},"required":["id","startAt","endAt","status"]},"message":{"type":"string"}},"required":["booking","message"]},"PublicBookRequest":{"type":"object","properties":{"startAt":{"type":"string","format":"date-time"},"code":{"type":"string","pattern":"^\\d{6}$"},"invitee":{"type":"object","properties":{"email":{"type":"string","format":"email"},"name":{"type":"string","minLength":1,"maxLength":120},"timezone":{"type":"string","minLength":1}},"required":["email","timezone"]},"customFields":{"type":"object","additionalProperties":{}},"guests":{"type":"array","items":{"type":"string","maxLength":254},"maxItems":10,"description":"Extra emails to add to the calendar invite."},"agentEmail":{"type":"string","format":"email","description":"The agent inbox you passed to `.../otp` — the code is checked against it and it's recorded as the booker acting for `invitee`."},"idempotencyKey":{"type":"string","minLength":8,"maxLength":128}},"required":["startAt","code","invitee"]},"PublicConfirmResponse":{"type":"object","properties":{"booking":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"startAt":{"type":"string","format":"date-time"},"endAt":{"type":"string","format":"date-time"},"status":{"type":"string"},"joinUrl":{"type":"string","format":"uri"}},"required":["id","startAt","endAt","status"]},"message":{"type":"string"}},"required":["booking","message"]},"PublicRescheduleResponse":{"type":"object","properties":{"booking":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"startAt":{"type":"string","format":"date-time"},"endAt":{"type":"string","format":"date-time"},"status":{"type":"string"},"joinUrl":{"type":"string","format":"uri"}},"required":["id","startAt","endAt","status"]},"message":{"type":"string"}},"required":["booking","message"]},"PublicRescheduleRequest":{"type":"object","properties":{"token":{"type":"string","minLength":1,"description":"Management token from the booking email"},"startAt":{"type":"string","format":"date-time","description":"New slot start, ISO 8601 UTC"}},"required":["token","startAt"]},"PublicCancelResponse":{"type":"object","properties":{"booking":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"}},"required":["id","status"]},"message":{"type":"string"}},"required":["booking","message"]},"PublicCancelRequest":{"type":"object","properties":{"token":{"type":"string","minLength":1,"description":"Management token from the booking email"},"reason":{"type":"string","maxLength":500}},"required":["token"]},"PublicManageCancelResponse":{"type":"object","properties":{"booking":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"}},"required":["id","status"]},"message":{"type":"string"}},"required":["booking","message"]},"PublicManageCancelRequest":{"type":"object","properties":{"token":{"type":"string","minLength":1,"description":"Management token from the booking email"},"reason":{"type":"string","maxLength":500}},"required":["token"]},"PublicManageRescheduleResponse":{"type":"object","properties":{"booking":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"startAt":{"type":"string","format":"date-time"},"endAt":{"type":"string","format":"date-time"},"status":{"type":"string"},"joinUrl":{"type":"string","format":"uri"}},"required":["id","startAt","endAt","status"]},"message":{"type":"string"}},"required":["booking","message"]},"PublicManageRescheduleRequest":{"type":"object","properties":{"token":{"type":"string","minLength":1,"description":"Management token from the booking email"},"startAt":{"type":"string","format":"date-time","description":"New slot start, ISO 8601 UTC"}},"required":["token","startAt"]},"WorkspaceApiKeyListResponse":{"type":"object","properties":{"keys":{"type":"array","items":{"$ref":"#/components/schemas/WorkspaceApiKeyMetadata"}},"visibility":{"type":"string","enum":["own","workspace"]}},"required":["keys","visibility"]},"WorkspaceApiKeyMetadata":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"prefix":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}},"createdByUserId":{"type":["string","null"],"format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"lastUsedAt":{"type":["string","null"],"format":"date-time"},"expiresAt":{"type":["string","null"],"format":"date-time"},"revokedAt":{"type":["string","null"],"format":"date-time"},"current":{"type":"boolean"}},"required":["id","name","prefix","scopes","createdByUserId","createdAt","lastUsedAt","expiresAt","revokedAt","current"]},"WorkspaceRevokeApiKeyResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["revoked"]}},"required":["id","status"]},"AgentSeatListResponse":{"type":"object","properties":{"seats":{"type":"array","items":{"$ref":"#/components/schemas/AgentSeat"}},"activeCount":{"type":"integer","minimum":0},"cap":{"type":"integer","exclusiveMinimum":0}},"required":["seats","activeCount","cap"]},"AgentSeat":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"displayName":{"type":"string"},"agentEmail":{"type":["string","null"],"format":"email"},"apiKeyId":{"type":"string","format":"uuid"},"createdByUserId":{"type":["string","null"],"format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"revokedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","displayName","agentEmail","apiKeyId","createdByUserId","createdAt","revokedAt"]},"AgentSeatCreateResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"displayName":{"type":"string"},"agentEmail":{"type":["string","null"],"format":"email"},"apiKeyId":{"type":"string","format":"uuid"},"apiKey":{"type":"string"},"prefix":{"type":"string"},"cap":{"type":"integer","exclusiveMinimum":0}},"required":["id","displayName","agentEmail","apiKeyId","apiKey","prefix","cap"]},"AgentSeatCreateRequest":{"type":"object","properties":{"displayName":{"type":"string","minLength":1,"maxLength":80},"agentEmail":{"type":"string","maxLength":254,"format":"email"}},"required":["displayName"]},"AgentSeatRevokeResponse":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"id":{"type":"string","format":"uuid"}},"required":["ok","id"]},"WorkspaceClaimIntentRequest":{"type":"object","properties":{"prospectEmail":{"type":"string","maxLength":254,"format":"email"},"agentName":{"type":"string","minLength":1,"maxLength":80}},"required":["prospectEmail"]},"StripeWebhookAck":{"type":"object","properties":{"received":{"type":"boolean","enum":[true]}},"required":["received"]}},"parameters":{}},"paths":{"/health":{"get":{"operationId":"health","summary":"Liveness probe + transport discovery.","description":"Stable, unauthenticated endpoint agents can hit to confirm the API is up and to discover the REST + MCP + OpenAPI URLs without parsing marketing copy. Append `?ready=1` for a readiness probe that also round-trips the database (200 `{status:\"ready\"}` / 503 `{status:\"not_ready\"}`) — intended for uptime monitors, not agents.","tags":["meta"],"security":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/cli/auth/register":{"post":{"operationId":"cli_auth_register","summary":"Start a CLI device-auth session and open a browser approval URL.","description":"Creates a pending device session. The CLI opens `verificationUrl` for the human to sign in and approve, then polls `GET /cli/auth/poll` with `deviceCode` until an API key is returned once.","tags":["cli"],"security":[],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliAuthRegisterRequest"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliAuthRegisterResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/cli/auth/poll":{"get":{"operationId":"cli_auth_poll","summary":"Poll a CLI device-auth session until approved (one-time key).","description":"Returns `authorization_pending` until the human approves in the browser. On success returns the workspace API key exactly once, then marks the session consumed.","tags":["cli"],"security":[],"parameters":[{"schema":{"type":"string","minLength":16,"maxLength":200},"required":true,"name":"device_code","in":"query"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliAuthPollResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/cli/calendars":{"get":{"operationId":"cli_list_calendars","summary":"List calendar connections for the API key owner/workspace.","description":"Used by `topcal calendars status` and by connect --wait to detect when OAuth has finished.","tags":["cli","calendar"],"security":[{"ApiKey":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliListCalendarsResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/cli/calendars/connect":{"post":{"operationId":"cli_connect_calendar","summary":"Mint a calendar OAuth URL for the key's user, or the human a bot works for.","description":"For a person's own key: opens Google or Microsoft consent for the user who created the key. For an **agent-seat** key: the link is for a human in the workspace — by default the person who approved the seat, or `forEmail`. Deliver `installUrl` to that person; only they, signed in to topcal as themselves, can complete it, and the calendar becomes theirs in this workspace. Each connected calendar is one billed calendar; agent seats are free. Poll GET /cli/calendars until the connection appears.","tags":["cli","calendar"],"security":[{"ApiKey":[]}],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliConnectCalendarRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliConnectCalendarResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/native/auth/email/start":{"post":{"operationId":"native_auth_email_start","summary":"Email a 6-digit sign-in code to the native app user.","description":"Starts in-app email sign-in (or sign-up) for the topcal iPhone, iPad and Mac apps. Responds identically for existing and new emails. The email subject is `Your topcal code: 123456` so iOS/macOS can autofill it. Codes expire after 10 minutes, allow 5 attempts, and a new start for the same email invalidates older codes. Disposable inboxes can't create accounts (`auth.email_not_allowed`). Rate-limited per email and per IP (429s include `Retry-After` / `RateLimit-*`). Responses that carry a challenge id use `Cache-Control: no-store`. Agent inboxes (e.g. mail.grokbot.com) must send `prospectEmail` before the first workspace is created. The human gets an emailed link, must approve, and is the owner. A bot that already holds a seat signs in without prospectEmail.","tags":["native-auth"],"security":[],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NativeAuthEmailStartRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NativeAuthEmailStartResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/native/auth/email/verify":{"post":{"operationId":"native_auth_email_verify","summary":"Exchange an emailed 6-digit code for a workspace API key.","description":"Signs in the existing user for the challenge's email, or creates the account (first workspace + 14-day Growth trial when eligible, `isNewAccount: true`). Agent-inbox first signups return `pending_claim` + `pollToken` instead of a key — the human must open the emailed link and press Approve first. A bot that already holds a seat gets a rotated key for that seat. Each successful ordinary verify mints a **new** key; older keys stay valid until `DELETE /workspace/api-keys/{id}`. Errors: 400 `auth.invalid_code` / `auth.prospect_email_required`, 410 `auth.code_expired`, 429 `rate.limited`.","tags":["native-auth"],"security":[],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NativeAuthEmailVerifyRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NativeAuthVerifyResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/native/auth/claim/poll":{"post":{"operationId":"native_auth_claim_poll","summary":"Poll a pending agent-inbox claim for the bot's seat API key.","description":"After `email/verify` returns `pending_claim`, poll with `pollToken`. Returns `pending_claim` until the human opens the magic link, then `claimed` with the seat API key once. Subsequent polls omit the secret. Expired or cancelled intents return 410 `auth.code_expired`.","tags":["native-auth"],"security":[],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NativeAuthClaimPollRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NativeAuthClaimPollResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/native/auth/apple":{"post":{"operationId":"native_auth_apple","summary":"Sign in (or sign up) with an Apple identity token.","description":"Verifies the Sign in with Apple identity token against Apple's JWKS (`iss` https://appleid.apple.com, `aud` one of the configured bundle IDs, `exp`, and `nonce == sha256(rawNonce)` hex). Maps the Apple `sub` to an existing account first, then the Apple-verified email (private relay addresses included), and creates the account when neither matches. Returns a `workspace.act` API key once. Invalid tokens return 401 `auth.invalid_identity_token`.","tags":["native-auth"],"security":[],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NativeAuthAppleRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NativeAuthResult"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/native/auth/passkey/options":{"post":{"operationId":"native_auth_passkey_options","summary":"Get WebAuthn assertion options for native passkey sign-in.","description":"Discoverable-credential assertion options for the same relying party the web login uses (RP ID `app.topcal.ai`): empty `allowCredentials`, `userVerification: \"required\"`. Pass `challengeId` back to `/native/auth/passkey/verify`.","tags":["native-auth"],"security":[],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NativeAuthPasskeyOptionsRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NativeAuthPasskeyOptionsResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/native/auth/passkey/verify":{"post":{"operationId":"native_auth_passkey_verify","summary":"Verify a passkey assertion and return a workspace API key.","description":"Passkey sign-in only (no registration). Binary fields are base64url. The assertion must be user-verified; origin, RP ID and signature are checked by the same verifier the web login uses. Returns a `workspace.act` API key once. Failures return 401 `auth.passkey_failed`.","tags":["native-auth"],"security":[],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NativeAuthPasskeyVerifyRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NativeAuthResult"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/agent/identities":{"post":{"operationId":"agent_register_identity","summary":"Declare a verified-human-on-whose-behalf the agent will act.","description":"Creates a pending `agent_principal` row scoped to the API key's workspace and emails the human a 6-digit OTP. The agent receives a stable `principalId` it can use to poll status and call `verify_agent_identity` once the human shares the code.","tags":["agent","identity"],"security":[{"ApiKey":[]}],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterAgentIdentityRequest"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterAgentIdentityResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/agent/identities/{principalId}/verify":{"post":{"operationId":"agent_verify_identity","summary":"Consume the OTP and return a delegated intent token.","description":"Confirms the human's consent for the listed scopes and mints a short-lived JWT bound to the verified principal. The agent uses this token in X-Topcal-Agent-Intent, alongside the same API key in Authorization: Bearer, for any operation that performs an action on behalf of this human (sign up, invite, pay, book).","tags":["agent","identity"],"security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"principalId","in":"path"}],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyAgentIdentityRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyAgentIdentityResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/agent/identities/{principalId}/revoke":{"post":{"operationId":"agent_revoke_identity","summary":"Revoke a verified principal.","description":"Either the agent (via API key) or the human (via support flow) can revoke. Once revoked, all outstanding intent tokens for the principal stop being honored on first use — verifications keep running for audit, but mutations are rejected.","tags":["agent","identity"],"security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"principalId","in":"path"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokeAgentIdentityResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/agent/users":{"post":{"operationId":"agent_signup_user","summary":"Provision a topcal user account on behalf of the verified human.","description":"Creates a `users` row keyed by the principal's email if one doesn't exist. Auto-accepts any pending workspace invitations addressed to that email and, if the user still has no memberships, creates their personal workspace.\n\nIdempotent on email — calling twice returns the same user row with `created: false` the second time.","tags":["agent","signup"],"security":[{"ApiKey":[],"AgentIntent":[]}],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupAgentUserRequest"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupAgentUserResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/agent/calendars/connect":{"post":{"operationId":"agent_connect_calendar","summary":"Mint a calendar-install URL for the verified human to click.","description":"Returns a single-use, signed install URL the agent can deliver to the human (chat, email, etc.). The OAuth dance happens inside the human's own browser session — the agent never sees the resulting calendar tokens. The connection lands on the `users` row whose email matches the verified principal's `prospectEmail`. Call `agent_signup_user` first if the user doesn't exist yet.\n\nTTL: 24 hours. POST again for a free fresh link — no extra charge.","tags":["agent","calendar"],"security":[{"ApiKey":[],"AgentIntent":[]}],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentConnectCalendarRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentConnectCalendarResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/agent/billing/checkout-intents":{"post":{"operationId":"agent_start_checkout","summary":"Start a Stripe Checkout session on behalf of a verified human.","description":"The agent declares which paid plan + interval + seat count the human wants (starter/solo = $20, plus = $49, growth/pro = $99; `pro` means Growth). We create a Stripe Checkout Session pre-bound to the workspace's customer + the verified principal, and return the URL the human visits to complete payment.\n\nThe agent never sees the human's payment method; Stripe owns that page. We mirror the session id locally as `agent_checkout_intents.id` so the agent (or a webhook subscriber) can poll for completion.","tags":["agent","billing"],"security":[{"ApiKey":[],"AgentIntent":[]}],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartCheckoutRequest"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartCheckoutResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/agent/billing/checkout-intents/{intentId}":{"get":{"operationId":"agent_get_checkout_intent","summary":"Poll the status of an agent-initiated Stripe Checkout.","description":"Returns `pending` until Stripe fires `checkout.session.completed` (see `/api/v1/webhooks/stripe`), at which point the row flips to `completed`. Use this in an agent loop to know when to follow up with the next step (e.g. `agent_create_workspace` or `book_on_behalf_of`).","tags":["agent","billing"],"security":[{"ApiKey":[],"AgentIntent":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"intentId","in":"path"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutIntentResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/agent/billing/enrichment-checkout-intents":{"post":{"operationId":"agent_start_enrichment_checkout","summary":"Start a Stripe Checkout session for enrichment credits.","description":"The agent declares which enrichment subscription tier or one-time credit pack the human wants. Returns a Stripe Checkout URL for the human to complete payment. Poll completion via GET /agent/billing/checkout-intents/{id}.","tags":["agent","billing","enrichment"],"security":[{"ApiKey":[],"AgentIntent":[]}],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartEnrichmentCheckoutRequest"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartEnrichmentCheckoutResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/agent/bookings":{"post":{"operationId":"agent_create_booking","summary":"Book a meeting on behalf of a verified human.","description":"Creates a real calendar event on the rep's connected calendar (Google Meet or Microsoft Teams auto-generated). The slot is re-validated at booking time to prevent double-booking. Supports idempotency via `idempotencyKey`.\n\nRequires a verified principal (see `agent/identities`) and the `agent.booking.write` scope.","tags":["agent","bookings"],"security":[{"ApiKey":[],"AgentIntent":[]}],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentCreateBookingRequest"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentCreateBookingResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/agent/bookings/{bookingId}":{"get":{"operationId":"agent_get_booking","summary":"Fetch a booking including form answers and host notes.","description":"Returns meeting details, invitee, labeled booking-form answers, keyed answers for agents, and private host notes for a booking in the authenticated workspace. Requires agent.booking.read scope.","tags":["agent","bookings"],"security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"bookingId","in":"path"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingDetailResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/agent/bookings/{bookingId}/enrichment":{"get":{"operationId":"agent_get_booking_enrichment","summary":"Fetch AI enrichment results for a booking.","description":"Returns Lead Magic person/company facts, optional Grok signals, prep brief, and lead score for a booking in the authenticated workspace. Requires agent.booking.read scope.","tags":["agent","enrichment"],"security":[{"ApiKey":[],"AgentIntent":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"bookingId","in":"path"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingEnrichmentResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/agent/bookings/{bookingId}/prep":{"get":{"operationId":"agent_get_booking_prep","summary":"Fetch the host-only Pre-Meeting Intelligence pack.","description":"Same artifact as GET /host/bookings/{bookingId}/prep. Raw enrichment facts stay on GET .../enrichment. Requires agent.booking.read. Never expose this pack to guests.","tags":["agent","prep"],"security":[{"ApiKey":[],"AgentIntent":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"bookingId","in":"path"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostPrepPack"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/agent/bookings/{bookingId}/reschedule":{"post":{"operationId":"agent_reschedule_booking","summary":"Reschedule a booking on behalf of a verified human.","description":"Moves an existing booking to a new slot. The slot is re-validated, the calendar event is moved (conference link preserved), and a reschedule email is sent. Requires a verified principal and `agent.booking.write`.","tags":["agent","bookings"],"security":[{"ApiKey":[],"AgentIntent":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"bookingId","in":"path"}],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRescheduleRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRescheduleResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/agent/bookings/{bookingId}/cancel":{"post":{"operationId":"agent_cancel_booking","summary":"Cancel a booking on behalf of a verified human.","description":"Cancels an existing booking: deletes the calendar event and sends a cancellation email. Requires a verified principal and `agent.booking.write`.","tags":["agent","bookings"],"security":[{"ApiKey":[],"AgentIntent":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"bookingId","in":"path"}],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentCancelRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentCancelResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/agent/event-types":{"get":{"operationId":"agent_list_event_types","summary":"List bookable event types for the authenticated workspace.","description":"Returns event types the agent can book on behalf of the verified principal. Includes attached form schema (if any) so agents know exactly what customFields to collect. Requires agent.booking.read scope.","tags":["agent","event-types"],"security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":["boolean","null"],"default":false},"required":false,"name":"includeInactive","in":"query"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"eventTypes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"durationMinutes":{"type":"number"},"locationType":{"type":"string"},"locationUrl":{"type":["string","null"]},"priceCents":{"type":["integer","null"]},"currency":{"type":["string","null"]},"allowAgentBooking":{"type":"boolean"},"isPubliclyListed":{"type":"boolean"},"form":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"definition":{"type":["object","null"],"properties":{"slug":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9-]+$"},"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":2000},"fields":{"type":"array","items":{"allOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"position":{"type":"integer","minimum":0},"key":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z][a-z0-9_]*$"},"label":{"type":"string","minLength":1,"maxLength":200},"placeholder":{"type":"string","maxLength":200},"helpText":{"type":"string","maxLength":500},"required":{"type":"boolean","default":false},"conditionalLogic":{"type":"object","properties":{"all":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string","minLength":1},"op":{"type":"string","enum":["eq","neq","in","not_in","contains","gte","lte","exists"]},"value":{}},"required":["field","op"]},"minItems":1}},"required":["all"]}},"required":["position","key","label"]},{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["short_text"]},"config":{"type":"object","properties":{"minLength":{"type":"integer","minimum":0},"maxLength":{"type":"integer","exclusiveMinimum":0},"pattern":{"type":"string"}}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","enum":["long_text"]},"config":{"type":"object","properties":{"minLength":{"type":"integer","minimum":0},"maxLength":{"type":"integer","exclusiveMinimum":0},"pattern":{"type":"string"}}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","enum":["email"]},"config":{"type":"object","properties":{"minLength":{"type":"integer","minimum":0},"maxLength":{"type":"integer","exclusiveMinimum":0},"pattern":{"type":"string"}}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","enum":["phone"]},"config":{"type":"object","properties":{"minLength":{"type":"integer","minimum":0},"maxLength":{"type":"integer","exclusiveMinimum":0},"pattern":{"type":"string"}}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","enum":["url"]},"config":{"type":"object","properties":{"minLength":{"type":"integer","minimum":0},"maxLength":{"type":"integer","exclusiveMinimum":0},"pattern":{"type":"string"}}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","enum":["number"]},"config":{"type":"object","properties":{"min":{"type":"number"},"max":{"type":"number"},"step":{"type":"number","exclusiveMinimum":0}}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","enum":["currency_range"]},"config":{"type":"object","properties":{"options":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1},"value":{"type":"string","minLength":1}},"required":["label","value"]},"minItems":2},"currency":{"type":"string","default":"USD"}},"required":["options"]}},"required":["type","config"]},{"type":"object","properties":{"type":{"type":"string","enum":["single_select"]},"config":{"type":"object","properties":{"options":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1},"value":{"type":"string","minLength":1},"description":{"type":"string"}},"required":["label","value"]},"minItems":1},"minSelections":{"type":"integer","minimum":0},"maxSelections":{"type":"integer","exclusiveMinimum":0},"allowOther":{"type":"boolean","default":false}},"required":["options"]}},"required":["type","config"]},{"type":"object","properties":{"type":{"type":"string","enum":["multi_select"]},"config":{"type":"object","properties":{"options":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1},"value":{"type":"string","minLength":1},"description":{"type":"string"}},"required":["label","value"]},"minItems":1},"minSelections":{"type":"integer","minimum":0},"maxSelections":{"type":"integer","exclusiveMinimum":0},"allowOther":{"type":"boolean","default":false}},"required":["options"]}},"required":["type","config"]},{"type":"object","properties":{"type":{"type":"string","enum":["radio"]},"config":{"type":"object","properties":{"options":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1},"value":{"type":"string","minLength":1},"description":{"type":"string"}},"required":["label","value"]},"minItems":1},"minSelections":{"type":"integer","minimum":0},"maxSelections":{"type":"integer","exclusiveMinimum":0},"allowOther":{"type":"boolean","default":false}},"required":["options"]}},"required":["type","config"]},{"type":"object","properties":{"type":{"type":"string","enum":["scale"]},"config":{"type":"object","properties":{"min":{"type":"integer"},"max":{"type":"integer"},"minLabel":{"type":"string"},"maxLabel":{"type":"string"}},"required":["min","max"]}},"required":["type","config"]},{"type":"object","properties":{"type":{"type":"string","enum":["date"]},"config":{"type":"object","properties":{"minDate":{"type":"string"},"maxDate":{"type":"string"},"format":{"type":"string","default":"yyyy-MM-dd"}}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","enum":["file"]},"config":{"type":"object","properties":{"maxSizeBytes":{"type":"integer","exclusiveMinimum":0,"default":10485760},"acceptedMimeTypes":{"type":"array","items":{"type":"string"},"default":[]},"multiple":{"type":"boolean","default":false}}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","enum":["boolean"]},"config":{"type":"object","properties":{"checkboxLabel":{"type":"string","maxLength":200},"mustBeTrue":{"type":"boolean"}}}},"required":["type"]}]}]},"minItems":1}},"required":["slug","name","fields"]}},"required":["id","definition"]}},"required":["id","slug","name","description","durationMinutes","locationType","locationUrl","priceCents","currency","allowAgentBooking","isPubliclyListed","form"]}}},"required":["eventTypes"]}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/host/bookings":{"get":{"operationId":"host_list_bookings","summary":"List workspace bookings in a time range (native host agenda).","description":"Returns the same booking detail shape as GET /agent/bookings/{id} for every meeting that overlaps [from, to). Form answers are empty on the list — fetch a single booking for labeled answers. Requires agent.booking.read or workspace.act.","tags":["host","bookings"],"security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Inclusive range start (ISO-8601)."},"required":true,"description":"Inclusive range start (ISO-8601).","name":"from","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Exclusive range end (ISO-8601)."},"required":true,"description":"Exclusive range end (ISO-8601).","name":"to","in":"query"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"bookings":{"type":"array","items":{"$ref":"#/components/schemas/BookingDetailResponse"}}},"required":["bookings"]}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/host/bookings/{bookingId}/prep":{"get":{"operationId":"host_get_booking_prep","summary":"Fetch the host-only Pre-Meeting Intelligence pack.","description":"Returns current structured prep for a booking in the authenticated workspace. Raw enrichment facts stay on GET .../enrichment. Host-only. Requires agent.booking.read or workspace.act. Uses existing research only; no supplier calls, stored prep, or credit charge.","tags":["host","prep"],"security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"bookingId","in":"path"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostPrepPack"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"host_regenerate_booking_prep","summary":"Refresh the host-only Pre-Meeting Intelligence pack.","description":"Force-rebuilds the prep pack from current enrichment, booking answers, host notes, and workspace guidance. No supplier calls or credit charge. Requires workspace.act or the legacy full workspace-tool scope set.","tags":["host","prep"],"security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"bookingId","in":"path"}],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"type":"object","properties":{"force":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostPrepPack"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/agent/slots/propose":{"post":{"operationId":"agent_propose_slots","summary":"Propose bookable slots for an event type.","description":"Returns UTC slot candidates the verified human can book, honoring availability rules, buffers, and busy time on the rep's connected calendar. Empty when no calendar is connected. Call this before POST /agent/bookings — the REST mirror of the MCP tool agent_propose_slots.\n\nRequires a verified principal and the `agent.booking.read` scope.","tags":["agent","bookings"],"security":[{"ApiKey":[],"AgentIntent":[]}],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentProposeSlotsRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentProposeSlotsResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/agent/availability/blocks":{"get":{"operationId":"agent_list_availability_blocks","summary":"List upcoming time-off blocks for the verified human.","description":"Returns full-day and partial-day availability blocks on the verified human's default schedule. Weekly hours are unchanged. Requires `agent.booking.read`.","tags":["agent","availability"],"security":[{"ApiKey":[],"AgentIntent":[]}],"parameters":[{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Inclusive YYYY-MM-DD lower bound (default: today)."},"required":false,"description":"Inclusive YYYY-MM-DD lower bound (default: today).","name":"fromDate","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Inclusive YYYY-MM-DD upper bound."},"required":false,"description":"Inclusive YYYY-MM-DD upper bound.","name":"toDate","in":"query"},{"schema":{"type":["boolean","null"],"default":false},"required":false,"name":"includePast","in":"query"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"scheduleId":{"type":"string","format":"uuid"},"blocks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"kind":{"type":"string","enum":["full_day","partial"]},"date":{"type":"string"},"startTime":{"type":["string","null"]},"endTime":{"type":["string","null"]},"reason":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}},"required":["id","kind","date","startTime","endTime","reason","createdAt"]}},"count":{"type":"integer"}},"required":["scheduleId","blocks","count"]}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"agent_add_availability_blocks","summary":"Block days or hours on the verified human's schedule.","description":"Creates temporary blocks without changing weekly availability. Omit startTime/endTime for full-day OOO (vacation). Include both for partial blocks (appointments). Example vacation: `{ \"fromDate\": \"2026-07-01\", \"toDate\": \"2026-07-07\", \"reason\": \"Vacation\" }`. Example appointment: `{ \"fromDate\": \"2026-06-20\", \"toDate\": \"2026-06-20\", \"startTime\": \"14:00\", \"endTime\": \"15:00\", \"reason\": \"Dentist\" }`. Requires `agent.booking.write`.","tags":["agent","availability"],"security":[{"ApiKey":[],"AgentIntent":[]}],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"type":"object","properties":{"fromDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"First blocked day (inclusive)."},"toDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Last blocked day (inclusive). Same as fromDate for a single day."},"startTime":{"type":"string","pattern":"^([01]\\d|2[0-3]):([0-5]\\d)(?::([0-5]\\d))?$","description":"Optional local start time (HH:mm). When set, endTime is required and creates partial blocks."},"endTime":{"type":"string","pattern":"^([01]\\d|2[0-3]):([0-5]\\d)(?::([0-5]\\d))?$","description":"Optional local end time (HH:mm). Required when startTime is set."},"reason":{"type":"string","maxLength":120,"description":"Optional label, e.g. \"Vacation\" or \"Dentist\"."}},"required":["fromDate","toDate"]}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"scheduleId":{"type":"string","format":"uuid"},"kind":{"type":"string","enum":["full_day","partial"]},"fromDate":{"type":"string"},"toDate":{"type":"string"},"startTime":{"type":["string","null"]},"endTime":{"type":["string","null"]},"reason":{"type":["string","null"]},"dates":{"type":"array","items":{"type":"string"}},"created":{"type":"integer"},"updated":{"type":"integer"}},"required":["scheduleId","kind","fromDate","toDate","startTime","endTime","reason","dates","created","updated"]}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"agent_remove_availability_blocks","summary":"Remove time-off blocks for a date range.","description":"Deletes blocks created via POST /agent/availability/blocks. Include startTime/endTime to remove partial blocks only. Requires `agent.booking.write`.","tags":["agent","availability"],"security":[{"ApiKey":[],"AgentIntent":[]}],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"type":"object","properties":{"fromDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"toDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"startTime":{"type":"string","pattern":"^([01]\\d|2[0-3]):([0-5]\\d)(?::([0-5]\\d))?$"},"endTime":{"type":"string","pattern":"^([01]\\d|2[0-3]):([0-5]\\d)(?::([0-5]\\d))?$"}},"required":["fromDate","toDate"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"scheduleId":{"type":"string","format":"uuid"},"fromDate":{"type":"string"},"toDate":{"type":"string"},"startTime":{"type":["string","null"]},"endTime":{"type":["string","null"]},"removed":{"type":"integer"}},"required":["scheduleId","fromDate","toDate","startTime","endTime","removed"]}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/public/{workspace}/{username}":{"get":{"operationId":"public_list_event_types","summary":"List a calendar owner's publicly bookable event types.","description":"Open, unauthenticated discovery for the booker plane. Returns the event types `{workspace}/{username}` has made public AND agent-bookable, each with its attached form definition so an agent knows exactly which fields to collect before booking. No API key required.","tags":["public","booking"],"security":[],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"workspace","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"username","in":"path"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicEventTypesResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/public/{workspace}/{username}/{eventSlug}/slots":{"get":{"operationId":"public_propose_slots","summary":"Propose available slots for a public event type.","description":"Open, unauthenticated availability for the booker plane. Returns bookable slots for `{workspace}/{username}/{eventSlug}`, honoring the owner's weekly hours (availability.hostSchedule), buffers, and live calendar conflicts. Pass `timezone` with the booker's IANA zone so each slot includes bookerLocal.display — never show raw UTC to humans. Default limit is 50 (max 240). No API key required.","tags":["public","booking"],"security":[],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"workspace","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"username","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"eventSlug","in":"path"},{"schema":{"type":"string","format":"date-time"},"required":false,"name":"from","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"name":"to","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":240,"description":"Max slots to return (default 50, max 240)."},"required":false,"description":"Max slots to return (default 50, max 240).","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Booker's IANA timezone — each slot includes bookerLocal display in this zone. Falls back to host timezone when omitted."},"required":false,"description":"Booker's IANA timezone — each slot includes bookerLocal display in this zone. Falls back to host timezone when omitted.","name":"timezone","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Inclusive local start date (YYYY-MM-DD, booker timezone) to narrow availability."},"required":false,"description":"Inclusive local start date (YYYY-MM-DD, booker timezone) to narrow availability.","name":"fromDate","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Inclusive local end date (YYYY-MM-DD, booker timezone) to narrow availability."},"required":false,"description":"Inclusive local end date (YYYY-MM-DD, booker timezone) to narrow availability.","name":"toDate","in":"query"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicSlotsResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/public/{workspace}/{username}/{eventSlug}/otp":{"post":{"operationId":"public_request_booking_otp","summary":"Request an email OTP to confirm a public booking.","description":"Step 1 of the open booker-plane booking flow. Emails a 6-digit code to the booker (or to `agentEmail` when an agent with its own inbox books for them); the agent relays it to POST `.../book`. No API key required. Disposable email addresses are rejected; requests are rate-limited per email and per IP.","tags":["public","booking"],"security":[],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"workspace","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"username","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"eventSlug","in":"path"}],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBookingOtpRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBookingOtpResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"get":{"operationId":"public_request_booking_otp_get","summary":"Request a booking OTP and a confirm URL (GET, web-fetch).","description":"Cold-booker (web_fetch) step 1. Pass the chosen slot + invitee as query params; we email a 6-digit code and return a `confirmUrl`. The agent then GETs `confirmUrl&code=<otp>` once the user reads the code back. The signed intent is embedded in confirmUrl (query param `confirmKey`) — there is no separate bookingToken field, so agent security scanners won't redact it. No API key, no POST required.","tags":["public","booking"],"security":[],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"workspace","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"username","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"eventSlug","in":"path"},{"schema":{"type":"string","format":"email"},"required":true,"name":"email","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Chosen slot start, ISO 8601 UTC"},"required":true,"description":"Chosen slot start, ISO 8601 UTC","name":"startAt","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Invitee IANA timezone"},"required":true,"description":"Invitee IANA timezone","name":"timezone","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":120},"required":false,"name":"name","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string","maxLength":2000},"required":false,"name":"guests","in":"query"},{"schema":{"type":"string","format":"email","description":"Your own inbox, when you are an AI agent booking for the human at `email`. The code is sent here instead of to the human; the calendar invite still goes to `email`."},"required":false,"description":"Your own inbox, when you are an AI agent booking for the human at `email`. The code is sent here instead of to the human; the calendar invite still goes to `email`.","name":"agentEmail","in":"query"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBookingOtpGetResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/public/{workspace}/{username}/{eventSlug}/book":{"post":{"operationId":"public_confirm_booking","summary":"Confirm a public booking with the email OTP.","description":"Step 2 of the open booker-plane flow. Consumes the OTP from `.../otp` (proving email control) and books the meeting via the shared createBooking path — real calendar event + confirmation email. No API key required.","tags":["public","booking"],"security":[],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"workspace","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"username","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"eventSlug","in":"path"}],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBookRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBookResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/public/{workspace}/{username}/{eventSlug}/confirm":{"get":{"operationId":"public_confirm_booking_get","summary":"Confirm a public booking with confirmKey + OTP (GET, web-fetch).","description":"Cold-booker (web_fetch) step 2. Verifies the signed confirmKey (from confirmUrl) and the OTP code, then books via the shared createBooking path (real calendar event + invite). Append `&code=` to the confirmUrl returned by GET .../otp. No API key, no POST required.","tags":["public","booking"],"security":[],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"workspace","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"username","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"eventSlug","in":"path"},{"schema":{"type":"string","minLength":1,"description":"Signed intent from confirmUrl (preferred)"},"required":false,"description":"Signed intent from confirmUrl (preferred)","name":"confirmKey","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Deprecated alias for confirmKey — kept for older links"},"required":false,"description":"Deprecated alias for confirmKey — kept for older links","name":"token","in":"query"},{"schema":{"type":"string","pattern":"^\\d{6}$","description":"Required when the host enforces email verification for agent bookings"},"required":false,"description":"Required when the host enforces email verification for agent bookings","name":"code","in":"query"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicConfirmResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/public/{workspace}/{username}/{eventSlug}/reschedule":{"post":{"operationId":"public_reschedule_booking","summary":"Reschedule a public booking with a management token.","description":"Moves an existing public booking to a new slot. The signed `token` from the booking's confirmation email authorizes the change (no API key). The calendar event is moved and the conference link preserved.","tags":["public","booking"],"security":[],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"workspace","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"username","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"eventSlug","in":"path"}],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicRescheduleRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicRescheduleResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/public/{workspace}/{username}/{eventSlug}/cancel":{"post":{"operationId":"public_cancel_booking","summary":"Cancel a public booking with a management token.","description":"Cancels an existing public booking. The signed `token` from the booking's confirmation email authorizes the change (no API key). The calendar event is deleted and a cancellation email is sent.","tags":["public","booking"],"security":[],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"workspace","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"username","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"eventSlug","in":"path"}],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCancelRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCancelResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/public/manage/cancel":{"post":{"operationId":"public_manage_cancel_booking","summary":"Cancel a booking with a management token.","description":"Cancels an existing booking. The signed `token` from the confirmation email authorizes the change (no API key, no event-type path). The calendar event is deleted and a cancellation email is sent.","tags":["public","booking"],"security":[],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicManageCancelRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicManageCancelResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/public/manage/reschedule":{"post":{"operationId":"public_manage_reschedule_booking","summary":"Reschedule a booking with a management token.","description":"Moves an existing booking to a new slot. The signed `token` from the confirmation email authorizes the change (no API key). The calendar event is moved and the conference link preserved.","tags":["public","booking"],"security":[],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicManageRescheduleRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicManageRescheduleResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/workspace/tools":{"get":{"operationId":"workspace_list_tools","summary":"List workspace tools the API key owner can run (same catalog as Cal Agent).","description":"Role-filtered catalog. Requires workspace.act (or a full MCP connector key) for full access; workspace.read permits six scheduling and prep read tools. MCP hosts call this for tools/list.","tags":["workspace"],"security":[{"ApiKey":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"tools":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"inputSchema":{"type":"object","additionalProperties":{}}},"required":["name","description","inputSchema"]}},"role":{"type":"string"},"workspace":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"]}},"required":["tools","role","workspace"]}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/workspace/tools/execute":{"post":{"operationId":"workspace_execute_tool","summary":"Run a Cal Agent workspace tool as the API key owner.","description":"Same executors as the in-app Cal Agent. Authorization is the owner's workspace role. Requires workspace.act (or a full MCP connector key) for full access; workspace.read permits six scheduling and prep read tools.","tags":["workspace"],"security":[{"ApiKey":[]}],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"arguments":{"type":"object","additionalProperties":{},"default":{}}},"required":["name"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"name":{"type":"string"},"result":{}},"required":["ok","name"]}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/workspace/agent/chat":{"post":{"operationId":"workspace_agent_chat","summary":"Talk to Cal Agent as the API key owner (native apps).","description":"Same agent loop, tools, approval flow and credit metering as the in-app Cal Agent drawer. The workspace is the API key's workspace. Mutating tool calls come back in `pending` unless `toolApprovalRequired` is false; resend them with `mode: \"execute_pending\"` to apply. Requires workspace.act.","tags":["workspace"],"security":[{"ApiKey":[]}],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","maxLength":8000,"default":""},"conversationId":{"type":["string","null"],"format":"uuid"},"history":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant"]},"content":{"type":"string","maxLength":8000}},"required":["role","content"]},"maxItems":32},"focus":{},"toolApprovalRequired":{"type":"boolean"},"mode":{"type":"string","enum":["chat","execute_pending"]},"pendingTools":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1},"name":{"type":"string","minLength":1},"arguments":{"type":"object","additionalProperties":{},"default":{}},"mutating":{"type":"boolean"}},"required":["id","name"]},"maxItems":20}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"conversationId":{"type":"string"},"title":{"type":"string"},"assistantMessage":{"type":"string"},"executed":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"ok":{"type":"boolean"},"result":{}},"required":["id","name","ok"]}},"pending":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"arguments":{"type":"object","additionalProperties":{}},"mutating":{"type":"boolean"}},"required":["id","name","arguments","mutating"]}},"pendingPreview":{"type":"array","items":{"type":"string"}},"navigateTo":{"type":["string","null"]}},"required":["conversationId","title","assistantMessage","executed","pending","pendingPreview","navigateTo"]}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/workspace/agent/conversations":{"get":{"operationId":"workspace_agent_conversations","summary":"List the API key owner's Cal Agent conversations, or load one by id.","description":"Without `id`, returns the conversation list (newest first). With `id`, returns that conversation and its messages. Same threads as the web Cal Agent drawer. Requires workspace.act.","tags":["workspace"],"security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":false,"name":"id","in":"query"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"conversations":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","title","updatedAt"]}},"conversation":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"messages":{}},"required":["id","title"]}}}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/workspace/api-keys":{"get":{"operationId":"workspace_list_api_keys","summary":"List API keys the caller may manage (metadata only).","description":"Returns prefixes, scopes, and timestamps — never the secret. Every key sees itself. A key holding `workspace.act` also sees the other keys its creator made, and — when that creator is an owner or admin (`api_keys.manage`) — every key in the workspace. A key without `workspace.act` (for example a read-only connector) sees only itself. Sign-in still issues a **new** key each time; use this list plus `DELETE /workspace/api-keys/{apiKeyId}` to revoke leftovers. Older keys are never auto-revoked.","tags":["workspace","api-keys"],"security":[{"ApiKey":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceApiKeyListResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/workspace/api-keys/{apiKeyId}":{"delete":{"operationId":"workspace_revoke_api_key","summary":"Revoke the current key, or (with workspace.act) keys you manage.","description":"Soft-revokes the key (`revokedAt`). Any key may revoke itself. Revoking another key requires the presenting key to hold `workspace.act`: then it may revoke keys its creator made, or — when that creator has `api_keys.manage` — any workspace key. Does not rotate or re-issue. Existing sign-in still mints a new key without revoking siblings.","tags":["workspace","api-keys"],"security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"apiKeyId","in":"path"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceRevokeApiKeyResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/workspace/agent-seats":{"get":{"operationId":"workspace_list_agent_seats","summary":"List free agent seats on this workspace.","description":"Metadata only. Owners and admins see every seat. `cap` follows the workspace's plan: Free 1, Starter 3, Plus 5, Growth 10 (a trial counts as Growth).","tags":["workspace","agent-seats"],"security":[{"ApiKey":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentSeatListResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"workspace_create_agent_seat","summary":"Mint a free, named, revocable agent seat.","description":"Creates an audited API key attributed to `displayName`. Activity is logged under that name. Does not consume a billed calendar seat. Refuses with `agent.seat_cap_reached` when the workspace is at its plan's cap (Free 1, Starter 3, Plus 5, Growth 10).","tags":["workspace","agent-seats"],"security":[{"ApiKey":[]}],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentSeatCreateRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentSeatCreateResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/workspace/agent-seats/{id}":{"delete":{"operationId":"workspace_revoke_agent_seat","summary":"Revoke an agent seat and its API key.","description":"Soft-revokes the seat and the bound API key. Calendars and billing on the workspace are not changed.","tags":["workspace","agent-seats"],"security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentSeatRevokeResponse"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/workspace/claim-intents":{"post":{"operationId":"workspace_start_claim_intent","summary":"Email a human a magic link to become owner of this workspace.","description":"Option A for an already-created bot-owned workspace: send a magic link to `prospectEmail`. They become `memberships.role=owner`. Billing, `createdByUserId`, and calendar bindings are not rewritten. Option B (attach an already-signed-in TopCal account that is not this email) is documented, not implemented.","tags":["workspace","ownership"],"security":[{"ApiKey":[]}],"requestBody":{"description":"Request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceClaimIntentRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NativeAuthPendingClaim"}}}},"400":{"description":"Invalid query, path, or body (`request.invalid`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing/invalid API key or agent intent (`auth.required`, `agent.intent.required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Workspace subscription inactive (`billing.upgrade_required`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Insufficient scope or principal state (`auth.forbidden`, `agent.principal.*`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found (`resource.not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict — slot taken, duplicate, etc. (`resource.conflict`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Semantic validation failed (`request.unprocessable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded (`rate.limited`). Includes `Retry-After` and `RateLimit-*` when the limiter exposes a window. Body and headers are `Cache-Control: no-store`.","headers":{"Retry-After":{"description":"Seconds until the caller may retry.","schema":{"type":"integer","minimum":1}},"RateLimit-Limit":{"description":"Requests allowed in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Remaining":{"description":"Requests left in the current window, when known.","schema":{"type":"integer","minimum":0}},"RateLimit-Reset":{"description":"Seconds until the window resets (same as Retry-After).","schema":{"type":"integer","minimum":1}},"RateLimit":{"description":"Combined `limit`, `remaining`, `reset` when known.","schema":{"type":"string"}},"Cache-Control":{"description":"Always `no-store` on v1 JSON (keys, codes, errors).","schema":{"type":"string","example":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Unexpected server error (`internal.unexpected`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Dependency unavailable (`service.unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/webhooks/stripe":{"post":{"operationId":"stripe_webhook","summary":"Stripe webhook receiver.","description":"Verifies the `Stripe-Signature` header against `STRIPE_WEBHOOK_SECRET` and updates `subscriptions` + `agent_checkout_intents` rows. The request body is the raw Stripe `Event` JSON (do NOT pre-parse).","tags":["billing","webhooks"],"security":[],"parameters":[{"schema":{"type":"string","description":"Stripe webhook signature"},"required":true,"description":"Stripe webhook signature","name":"stripe-signature","in":"header"}],"responses":{"200":{"description":"Event acknowledged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StripeWebhookAck"}}}},"400":{"description":"Signature mismatch / malformed request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Stripe is not configured on this deployment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}}},"webhooks":{}}