{"schemaVersion":"2026-06-23.2","docs":{"openapi":"https://app.elsewhereventures.com/api/openapi","llms":"https://app.elsewhereventures.com/llms.txt","llmsFull":"https://app.elsewhereventures.com/llms-full.txt","mcp":"https://app.elsewhereventures.com/api/v1/mcp"},"auth":{"botApiKeyHeader":"Authorization: Bearer <BOT_API_KEY>","alternativeBotApiKeyHeader":"X-API-Key: <BOT_API_KEY>","managedKeysUiPath":"/settings","keySources":["managed key","BOT_API_KEYS env"],"mcpKeyHeader":"Authorization: Bearer <CLIENT_API_KEY>","mcpManagedKeysUiPath":"/clients/{clientId}"},"mcp":{"endpoint":"https://app.elsewhereventures.com/api/v1/mcp","transport":"streamable-http","readOnly":false,"writeTools":["create_gift","redeem_gift","extend_gift"],"toolCount":17},"endpoints":[{"path":"/api/health","methods":["GET"],"auth":"none","cache":"no-store, max-age=0"},{"path":"/api/v1/capabilities","methods":["GET"],"auth":"none","cache":"public, max-age=300, stale-while-revalidate=600"},{"path":"/api/v1/public/trips/{shareToken}/itinerary","methods":["GET"],"auth":"none","cache":"public, max-age=60, stale-while-revalidate=300","notes":"Read-only itinerary payload for shared trip links."},{"path":"/api/v1/public/trips/{shareToken}/rsvp","methods":["POST"],"auth":"none","cache":"no-store, max-age=0","notes":"Guest RSVP for optional trip activities. Unauthenticated; gated by share token. Body: { tripItemId, clientContactId, response }."},{"path":"/api/v1/public/trips/{shareToken}/guest-preferences","methods":["POST"],"auth":"none","cache":"no-store, max-age=0","notes":"Submit guest dietary restrictions and notes. Unauthenticated; gated by share token. Body: { clientContactId, dietaryRestrictions, notes }."},{"path":"/api/v1/public/trips/{shareToken}/intake","methods":["POST"],"auth":"none","cache":"no-store, max-age=0","notes":"Submit guest intake form. Unauthenticated; gated by share token. Body: { firstName, lastName, email, phone?, dietaryRestrictions?, passportNumber?, passportExpiry?, nationality?, dateOfBirth?, knownTraveler?, globalEntry?, loyaltyPrograms?, customAnswers? }."},{"path":"/api/v1/public/guests/{personalToken}/polls/{pollId}/respond","methods":["POST"],"auth":"none","cache":"no-store, max-age=0","notes":"Submit a guest's poll response from a personal share link. Unauthenticated; gated by personal token. Polls support three answer types: choice (single option), text (free response), and slot_signup (option + HH:MM time within a configured window). Polls may carry an optional reference link (linkUrl + linkLabel) shown to guests as a button. Body: { answer, tripId } for choice/text; for slot_signup, body is { option, time, tripId }."},{"path":"/api/v1/public/trips/{shareToken}/polls/{pollId}/respond","methods":["POST"],"auth":"none","cache":"no-store, max-age=0","notes":"Submit a guest's poll response from the broadcast share link. Unauthenticated; requires the intake_guest_<shareToken> cookie issued on intake completion. Same poll types and link semantics as the personal-token endpoint. Body: { answer } for choice/text; for slot_signup, body is { option, time }."},{"path":"/api/v1/host/trips/{tripId}/polls/{pollId}/responses.csv","methods":["GET"],"auth":"session","cache":"no-store","notes":"Download poll responses as CSV (UTF-8). Authenticated session required (advisor owner, admin, attached client, or host contact). Columns vary by poll type: slot_signup → Name, Email, Treatment, Time, Responded At; choice/text → Name, Email, Answer, Responded At."},{"path":"/api/v1/bot/whoami","methods":["GET"],"auth":"bearer","scopes":["trips.read","trips.*","events.read","events.*","gifts.read","gifts.*","export.read","export.*","webhooks.read","webhooks.*","client-api-keys.read","client-api-keys.*","bot.info","mutations.trips","mutations.expenses","mutations.payments","mutations.commissions","mutations.points","mutations.gifts","mutations.bulk","mutations.webhooks","mutations.client-api-keys","mutations.*","*"],"cache":"private, max-age=30, stale-while-revalidate=60","notes":"Resolve bot identity with any valid bot key scope."},{"path":"/api/v1/mcp","methods":["GET","POST"],"auth":"bearer","cache":"no-store, max-age=0","notes":"Client-scoped MCP endpoint using streamable HTTP transport. Mostly read-only; also exposes gift actions (create_gift, redeem_gift, extend_gift) that fire the same audit-log + webhook side-effects as the bot API. Tokens are issued per client record in the dashboard."},{"path":"/api/v1/bot/events","methods":["GET"],"auth":"bearer","scopes":["events.read","events.*"],"cache":"private, max-age=15, stale-while-revalidate=30"},{"path":"/api/v1/bot/export/trips","methods":["GET"],"auth":"bearer","scopes":["export.read","export.*"],"cache":"private, max-age=30, stale-while-revalidate=60"},{"path":"/api/v1/bot/stream","methods":["GET"],"auth":"bearer","scopes":["events.read","events.*"],"cache":"no-cache","notes":"SSE real-time event stream. Supports ?since= cursor and auto-reconnect. Max 2 concurrent connections per token."},{"path":"/api/v1/bot/trips/{id}/insights","methods":["GET"],"auth":"bearer","scopes":["trips.read","trips.*"],"cache":"private, max-age=30, stale-while-revalidate=60","notes":"Trip intelligence insights: payment alerts, completeness checks, timeline warnings, and accounting observations."},{"path":"/api/v1/bot/query","methods":["POST"],"auth":"bearer","scopes":["trips.read","trips.*"],"cache":"private, max-age=15, stale-while-revalidate=30","notes":"Natural language query endpoint. Accepts { question: string } and returns structured answers about balances, spending, upcoming trips, and payments."},{"path":"/api/v1/bot/trips/{id}/actions","methods":["GET"],"auth":"bearer","scopes":["trips.read","trips.*"],"cache":"private, max-age=30, stale-while-revalidate=60","notes":"Next-action suggestions for a trip: payment reminders, missing data, status updates. Actions marked advisory=true are suggestions only."},{"path":"/api/v1/bot/trips/{id}/guests","methods":["GET"],"auth":"bearer","scopes":["trips.read","trips.*"],"cache":"no-store, max-age=0","notes":"List a trip's guests (contacts) with their per-trip details. Returns guest PII; requires bearer + trips.read."},{"path":"/api/v1/bot/trips/{id}/rooms","methods":["GET","POST"],"auth":"bearer","scopes":["trips.read","trips.*","mutations.trips","mutations.*","*"],"cache":"no-store, max-age=0","notes":"List a trip's rooms (GET, trips.read) or add a room (POST, mutations.trips)."},{"path":"/api/v1/public/trips/{shareToken}/intake/upload","methods":["POST"],"auth":"none","cache":"no-store, max-age=0","notes":"Unauthenticated, share-token gated. Uploads a guest intake file (e.g., passport image) for the shared trip."},{"path":"/api/v1/bot/trips","methods":["GET","POST"],"auth":"bearer","scopes":["trips.read","trips.*","mutations.trips","mutations.*","*"],"cache":"no-store, max-age=0","notes":"GET: List trips with cursor or offset pagination (?cursor=<id>, ?page=<n>, ?limit=<n>, ?tripId=<id>). Cursor-based is recommended. POST: Create a trip with optional multi-client split rows; persists the primary client plus all trip participants in one write. Supports ?dryRun=true to preview without writing."},{"path":"/api/v1/bot/trips/{id}","methods":["PUT","DELETE"],"auth":"bearer","scopes":["mutations.trips","mutations.*","*"],"cache":"no-store, max-age=0","notes":"Update or soft-delete a trip by ID, including primary client and split-trip participant rows. Supports ?dryRun=true to preview without writing."},{"path":"/api/v1/bot/expenses","methods":["GET","POST"],"auth":"bearer","scopes":["trips.read","trips.*","mutations.expenses","mutations.*","*"],"cache":"no-store, max-age=0","notes":"GET: List expenses with cursor or offset pagination (?cursor=<id>, ?page=<n>, ?limit=<n>, ?tripId=<id>). Cursor-based is recommended. POST: Create an expense with optional per-client assignments (multi-client split) and auto-linked trip item / commission."},{"path":"/api/v1/bot/expenses/{id}","methods":["PUT","DELETE"],"auth":"bearer","scopes":["mutations.expenses","mutations.*","*"],"cache":"no-store, max-age=0","notes":"Update or soft-delete an expense by ID."},{"path":"/api/v1/bot/expenses/bulk","methods":["POST"],"auth":"bearer","scopes":["mutations.bulk","mutations.*","*"],"cache":"no-store, max-age=0","notes":"Bulk-create up to 50 expenses. Supports per-expense `assignments: [{clientId, weight}]` for multi-client splits."},{"path":"/api/v1/bot/payments","methods":["GET","POST"],"auth":"bearer","scopes":["trips.read","trips.*","mutations.payments","mutations.*","*"],"cache":"no-store, max-age=0","notes":"GET: List payments with cursor or offset pagination (?cursor=<id>, ?page=<n>, ?limit=<n>, ?tripId=<id>). Cursor-based is recommended. POST: Create a payment with optional trip-participant clientId attribution."},{"path":"/api/v1/bot/payments/{id}","methods":["PUT","DELETE"],"auth":"bearer","scopes":["mutations.payments","mutations.*","*"],"cache":"no-store, max-age=0","notes":"Update or soft-delete a payment by ID."},{"path":"/api/v1/bot/payments/bulk","methods":["POST"],"auth":"bearer","scopes":["mutations.bulk","mutations.*","*"],"cache":"no-store, max-age=0","notes":"Bulk-create up to 50 payments. Supports clientId per payment for shared trips."},{"path":"/api/v1/bot/commissions","methods":["GET","POST"],"auth":"bearer","scopes":["trips.read","trips.*","mutations.commissions","mutations.*","*"],"cache":"no-store, max-age=0","notes":"GET: List commissions with cursor or offset pagination (?cursor=<id>, ?page=<n>, ?limit=<n>, ?tripId=<id>). Cursor-based is recommended. POST: Create a commission entry."},{"path":"/api/v1/bot/commissions/{id}","methods":["PUT","DELETE"],"auth":"bearer","scopes":["mutations.commissions","mutations.*","*"],"cache":"no-store, max-age=0","notes":"Update or soft-delete a commission entry by ID."},{"path":"/api/v1/bot/points","methods":["GET","POST"],"auth":"bearer","scopes":["trips.read","trips.*","mutations.points","mutations.*","*"],"cache":"no-store, max-age=0","notes":"GET: List points entries with cursor or offset pagination (?cursor=<id>, ?page=<n>, ?limit=<n>, ?tripId=<id>). Cursor-based is recommended. POST: Create a points redemption entry."},{"path":"/api/v1/bot/points/{id}","methods":["PUT","DELETE"],"auth":"bearer","scopes":["mutations.points","mutations.*","*"],"cache":"no-store, max-age=0","notes":"Update or soft-delete a points entry by ID."},{"path":"/api/v1/bot/gifts","methods":["GET","POST"],"auth":"bearer","scopes":["gifts.read","gifts.*","mutations.gifts","mutations.*","*"],"cache":"no-store, max-age=0","notes":"GET: List gifts with cursor pagination plus optional status and gifterId filters. POST: Create a gift for a client."},{"path":"/api/v1/bot/gifts/{id}","methods":["GET","PUT","DELETE"],"auth":"bearer","scopes":["gifts.read","gifts.*","mutations.gifts","mutations.*","*"],"cache":"no-store, max-age=0","notes":"GET: Gift detail. PUT: Update gift (status, notes, extend expiry, link trip). DELETE: Soft delete."},{"path":"/api/v1/bot/gifts/{id}/redeem","methods":["POST"],"auth":"bearer","scopes":["mutations.gifts","mutations.*","*"],"cache":"no-store, max-age=0","notes":"Mark a gift as redeemed. Accepts recipient name, email, phone."},{"path":"/api/v1/bot/gifts/{id}/celebrate","methods":["POST"],"auth":"bearer","scopes":["mutations.gifts","mutations.*","*"],"cache":"no-store, max-age=0","notes":"Trigger the celebration email to the gifter."},{"path":"/api/v1/bot/webhooks","methods":["GET","POST"],"auth":"bearer","scopes":["webhooks.read","webhooks.*","mutations.webhooks","mutations.*","*"],"cache":"no-store, max-age=0","notes":"GET: List advisor webhook endpoints plus queue stats. POST: Create a webhook endpoint and return the signing secret once."},{"path":"/api/v1/bot/webhooks/{id}","methods":["PUT","DELETE"],"auth":"bearer","scopes":["mutations.webhooks","mutations.*","*"],"cache":"no-store, max-age=0","notes":"Update webhook endpoint URL/events/active state or delete it. Pausing/resuming automatically updates queued delivery status."},{"path":"/api/v1/bot/webhooks/deliveries","methods":["GET"],"auth":"bearer","scopes":["webhooks.read","webhooks.*","mutations.webhooks","mutations.*","*"],"cache":"no-store, max-age=0","notes":"List recent webhook deliveries with optional endpointId, status, and limit filters. Use this to inspect failure history before replaying."},{"path":"/api/v1/bot/webhooks/deliveries/{id}/replay","methods":["POST"],"auth":"bearer","scopes":["mutations.webhooks","mutations.*","*"],"cache":"no-store, max-age=0","notes":"Replay a prior webhook delivery by ID. Returns the new replay delivery ID and immediate retry status."},{"path":"/api/v1/bot/clients/{clientId}/api-keys","methods":["GET","POST"],"auth":"bearer","scopes":["client-api-keys.read","client-api-keys.*","mutations.client-api-keys","mutations.*","*"],"cache":"no-store, max-age=0","notes":"List or create client-scoped MCP API keys for a specific client record. POST returns the raw token once."},{"path":"/api/v1/bot/clients/{clientId}/api-keys/{keyId}","methods":["DELETE"],"auth":"bearer","scopes":["mutations.client-api-keys","mutations.*","*"],"cache":"no-store, max-age=0","notes":"Revoke a client-scoped MCP API key by ID for the specified client record."}]}