{"version":"0.1.0","routes":{"suggestions":{"matches":{"path":"/suggestions/matches","methods":["POST"],"description":"Record client-detected detection-pattern matches"},"dismiss":{"path":"/suggestions/{source_slug}/dismiss","methods":["POST","DELETE"],"description":"Dismiss (POST) or undismiss (DELETE) a suggestion for a source"},"list":{"path":"/suggestions","methods":["GET"],"description":"List ranked suggested integrations for the authenticated user"}},"connections":{"refresh":{"path":"/connections/{id}/refresh","methods":["POST"],"description":"Refresh OAuth tokens - uses server credentials but returns tokens to client without storing"},"get":{"path":"/connections/{id}","methods":["GET","PATCH","DELETE"],"description":"Get, update, or permanently destroy a connection"},"tokens":{"path":"/connections/{id}/tokens","methods":["GET","PUT"],"description":"Get or store client-encrypted OAuth tokens for portable access"},"disconnect":{"path":"/connections/{id}/disconnect","methods":["POST"],"description":"Disconnect while preserving the current connection snapshot"},"connect":{"path":"/connections/connect","methods":["POST"],"description":"Exchange OAuth code for tokens - returns tokens to client without storing on server"},"initiate":{"path":"/connections/initiate","methods":["POST"],"description":"Initiate OAuth flow - returns OAuth URL for client to open"},"list":{"path":"/connections","methods":["GET","POST"],"description":"List and create connections"}},"account":{"refresh":{"path":"/account/refresh","methods":["POST"],"description":"Refresh access token using a valid refresh token (body or HttpOnly cookie)"},"connect":{"path":"/account/connect","methods":["POST"],"description":"Unified authentication - handles discovery, password auth, OAuth initiation, and OAuth callback all in one endpoint"},"totp-enroll":{"path":"/account/totp/enroll","methods":["POST"],"description":"Begin TOTP enrollment"},"sessions":{"path":"/account/sessions","methods":["GET","DELETE"],"description":"List or revoke all browser sessions"},"totp-status":{"path":"/account/totp","methods":["GET"],"description":"Get two-step verification status"},"security-step-up":{"path":"/account/security/step-up","methods":["POST"],"description":"Begin a purpose-bound security-management step-up"},"password-change":{"path":"/account/password","methods":["POST"],"description":"Change an existing password after current-password verification; invalidates refresh sessions"},"session":{"path":"/account/sessions/{id}","methods":["DELETE"],"description":"Revoke one browser session"},"totp-confirm":{"path":"/account/totp/confirm","methods":["POST"],"description":"Confirm TOTP enrollment"},"totp-regenerate":{"path":"/account/totp/recovery-codes","methods":["POST"],"description":"Regenerate recovery codes after TOTP step-up"},"email-change-confirm":{"path":"/account/email-change/confirm","methods":["POST"],"description":"Consume an email-verification token plus fresh security proof"},"oauth-method-link":{"path":"/account/auth-methods/{provider}/link","methods":["POST"],"description":"Begin a purpose-bound single-use OAuth login-method link"},"panel-login-exchange":{"path":"/account/panel-login/exchange","methods":["POST"],"description":"Exchange a panel handoff ticket (from the URL fragment) for a browser session"},"logout":{"path":"/account/logout","methods":["POST"],"description":"Clear session cookies for browser clients"},"me":{"path":"/account/me","methods":["GET","PATCH","DELETE"],"description":"Get, update, or schedule deletion of the current user (DELETE soft-deletes with a 7-day grace period)"},"password-method-add":{"path":"/account/auth-methods/password","methods":["POST"],"description":"Add password sign-in after fresh security proof"},"password-reset-request":{"path":"/account/password-reset/request","methods":["POST"],"description":"Start a password-reset flow by emailing a single-use link to the address on file. Always 204; rate-limited per user."},"panel-login":{"path":"/account/panel-login","methods":["POST"],"description":"Mint a single-use panel auto-login link for the authenticated user (native app → signed-in panel)"},"cancel-deletion":{"path":"/account/me/cancel-deletion","methods":["POST"],"description":"Cancel a pending account deletion during the grace window"},"profiles-key":{"path":"/account/profiles/key","methods":["GET","POST","PUT"],"description":"Manage encrypted sync key for primary profile (GET: retrieve, POST: create, PUT: update)"},"oauth-security-reauth":{"path":"/account/security/reauth/{provider}","methods":["POST"],"description":"Begin purpose-bound provider reauthentication"},"profiles":{"path":"/account/profiles","methods":["GET"],"description":"List user authentication profiles"},"auth-methods":{"path":"/account/auth-methods","methods":["GET"],"description":"List non-secret linked sign-in method status"},"totp-disable":{"path":"/account/totp","methods":["DELETE"],"description":"Disable TOTP after step-up"},"oauth-method-callback":{"path":"/account/auth-methods/oauth/callback","methods":["POST"],"description":"Complete an authenticated OAuth login-method link without implicit login linking"},"totp-challenge":{"path":"/account/totp/challenge","methods":["POST"],"description":"Complete a single-use login two-step challenge"},"email-change-request":{"path":"/account/email-change/request","methods":["POST"],"description":"Request a verified canonical email change after fresh security proof"},"auth-method-remove":{"path":"/account/auth-methods/{source}","methods":["DELETE"],"description":"Remove one selected sign-in profile after fresh security proof"},"profiles-key-source":{"path":"/account/profiles/{source}/key","methods":["GET"],"description":"Get encrypted sync key for a specific source profile"},"deletion-status":{"path":"/account/deletion-status","methods":["GET"],"description":"Read pending-deletion status with a recovery-scoped session"},"password-reset-confirm":{"path":"/account/password-reset/confirm","methods":["POST"],"description":"Complete a password reset by redeeming the token and setting a new password. Invalidates all existing refresh tokens."},"oauth-security-reauth-callback":{"path":"/account/security/reauth/callback","methods":["POST"],"description":"Complete provider reauthentication and issue a one-use proof"}},"capabilities":{"list":{"path":"/capabilities","methods":["GET"],"description":"List all available capabilities"}},"webhooks":{"inbound":{"path":"/webhook/{source}/{capability}/{webhook_id}","methods":["POST"],"description":"Generic webhook bridge - validates the provider's verification token and wakes the user's devices to sync the channel"},"registration":{"path":"/webhook-registrations/{webhook_id}","methods":["PUT","DELETE"],"description":"Upsert or delete a webhook routing registration (client-side watch registration)"},"gmail-push":{"path":"/webhook/gmail/push","methods":["POST"],"description":"Shared-topic Gmail Pub/Sub push - OIDC-verified, routes by mailbox address and wakes the user's devices to sync"}},"ai":{"models":{"path":"/ai/models","methods":["POST"],"description":"Query AI models compatible with the requesting device (send device capabilities in body)"},"prompts":{"path":"/ai/prompts","methods":["GET"],"description":"List on-device AI prompts (reference data the client syncs into the core)"}},"channels":{"rename":{"path":"/channels/{id}/rename","methods":["POST"],"description":"Rename a calendar channel on its provider"},"discover":{"path":"/channels/discover","methods":["POST"],"description":"Discover and create channels for a connection"},"list":{"path":"/channels","methods":["GET"],"description":"List channels for a connection (requires ?connection_id=UUID)"},"detail":{"path":"/channels/{id}","methods":["GET","PATCH"],"description":"Get or update a specific channel"}},"categories":{"list":{"path":"/categories","methods":["GET"],"description":"List all available categories"}},"ops":{"sentry-test":{"path":"/ops/debug/sentry","methods":["GET"],"description":"Operator-only Sentry self-test: emits a deliberate error to verify capture works. Requires ADMIN_API_TOKEN env var and Authorization: Bearer header."},"push-test":{"path":"/ops/push/test","methods":["GET"],"description":"Operator-only push pipeline test (dry-run by default). Requires ADMIN_API_TOKEN env var and Authorization: Bearer header."}},"devices":{"key-request":{"path":"/account/devices/{device_id}/key-request","methods":["GET","POST"],"description":"Key exchange: POST public key (new device) or GET pending public key (existing device)"},"key-response":{"path":"/account/devices/{device_id}/key-response","methods":["POST"],"description":"Existing device posts wrapped master key for requesting device"},"key-transfer":{"path":"/account/devices/{device_id}/key-transfer","methods":["GET"],"description":"New device retrieves and consumes the wrapped master key"},"detail":{"path":"/account/devices/{device_id}","methods":["GET","PUT","DELETE"],"description":"Get, update, or delete a specific device"},"key-rotation":{"path":"/account/devices/key-rotation","methods":["POST"],"description":"Notify all devices that a key rotation has occurred"},"list":{"path":"/account/devices","methods":["GET","POST"],"description":"List and register devices"},"pairing-code":{"path":"/account/devices/{device_id}/pairing-code","methods":["POST"],"description":"Generate a 6-digit pairing code for QR-based device setup"},"push-token":{"path":"/account/devices/{device_id}/push-token","methods":["POST"],"description":"Register or clear push notification token for a device"}},"billing":{"checkout":{"path":"/billing/checkout","methods":["POST"],"description":"Create a Stripe Checkout session for the chosen plan term; returns the hosted URL"},"webhook":{"path":"/billing/webhook","methods":["POST"],"description":"Stripe webhook ingest (signature-verified); keeps subscription/invoice state in sync"},"portal":{"path":"/billing/portal","methods":["POST"],"description":"Create a Stripe Customer Portal session; returns the hosted URL"}},"exports":{"step-up":{"path":"/account/exports/step-up","methods":["POST"],"description":"Create a single-use TOTP challenge for export"},"authorize":{"path":"/account/exports/{id}/authorize","methods":["POST"],"description":"Issue a short-lived one-time download authorization"},"download":{"path":"/account/exports/{id}/download","methods":["POST"],"description":"Authenticated short-lived export download"},"list":{"path":"/account/exports","methods":["GET","POST"],"description":"List exports or start one after fresh password/TOTP step-up"},"status":{"path":"/account/exports/{id}","methods":["GET"],"description":"Get an owned export status"}},"keys":{"list":{"path":"/account/keys","methods":["GET"],"description":"List unlock methods (recovery_code, passphrase) — metadata only"},"claim":{"path":"/account/keys/claim","methods":["POST"],"description":"Atomically claim the first wrapped master-key blob"},"kind":{"path":"/account/keys/{kind}","methods":["GET","PUT","DELETE"],"description":"Fetch, upsert, or remove a wrapped master-key blob"}},"sources":{"list":{"path":"/sources","methods":["GET"],"description":"List all sources with embedded capabilities and categories"},"get":{"path":"/sources/{id}","methods":["GET"],"description":"Get a specific source with embedded capabilities and categories"}},"general":{"health":{"path":"/health","methods":["GET"],"description":"Liveness check — is the process up (no dependency probe)"},"readiness":{"path":"/health/ready","methods":["GET"],"description":"Readiness probe — checks database and NATS connectivity (503 if unavailable)"},"index":{"path":"/","methods":["GET"],"description":"API index and documentation"}}}}