← Ambasdr Docs
API Reference

API Endpoints and Authentication

All REST endpoints grouped by security scheme, with request/response shapes and the SSE streaming protocol for chat.

01

Security Schemes

The API uses four distinct authentication methods depending on the caller.

Bearer JWT

Authenticated Users

Auth0-issued RS256 JWT with JWKS validation. Custom claims at https://ambasdr.com/user_id and https://ambasdr.com/role. Used by all /v1/* protected routes. Header: Authorization: Bearer <token>.

M2M Secret

Auth0 Post-Login Action

Shared secret for machine-to-machine communication. Used only by POST /internal/users/provision. Header: Authorization: Bearer <M2M_SECRET>.

API Key

Python Voice Agent

Shared secret for the LiveKit agent's backend calls. Used by all /v1/agent/* routes. Header: X-API-Key: <AGENT_API_KEY>.

Optional JWT

Room Token

Bearer JWT is accepted but not required on POST /v1/pages/:page_id/room-token. If present, the caller is identified as the page owner. If absent, the caller is treated as a visitor.

02

Public Endpoints

No authentication required. These endpoints serve the public-facing page and chat experience.

Endpoint Description
GET /v1/public/pages/:slug Returns full public page data: page info (slug, title, description, user_types), user profile (display_name, avatar_url, bio), social_links array, theme settings, and agent config (agent_name, greeting_message).
POST /v1/public/pages/:slug/chat Streams an AI chat response via SSE. Body: {"message": "...", "thread_id": "optional-uuid"}. Returns event stream (see SSE Protocol section).
03

User Management

Bearer JWT required. Manage the authenticated user's profile. All three endpoints share the same identity-resolution chain — see Architecture §10 (Authentication and User Identity Resolution) for the full lookup priority.

Endpoint Description
GET /v1/me Returns the authenticated user's profile. Also updates last_login_at. Lazily provisions the user row if the JWT carries a valid sub claim but no Ambasdr user row exists yet — never 404 on a token-valid caller.
PUT /v1/me Update profile fields. Body: {"display_name": "...", "avatar_url": "...", "bio": "..."}. All fields optional. Lazy-provisions the user the same way GET does, then applies the update.
DELETE /v1/me Soft-delete the user account. Sets deleted_at timestamp. Subsequent authenticated calls with the same Auth0 sub return 404 user account has been deleted — the lazy-provisioning chain detects soft-deleted rows and refuses to re-create.
04

Onboarding

Bearer JWT required. Single-submission endpoint that creates the user's page, uploads documents, and triggers agent instruction generation.

Endpoint Description
POST /v1/onboarding Multipart form. Fields: first_name, last_name, slug, user_types (JSON), descriptor, agent_system_prompt, agent_focus, social_links (JSON), custom_links (JSON), document_contexts (JSON). Files: profile_image, documents[]. Returns: {"page_id": "uuid", "page_slug": "slug"}.
GET /v1/availability?slug=X Check if a slug is available. Returns: {"available": true|false}. Validates format (lowercase, alphanumeric, hyphens) and checks uniqueness.
Onboarding is Idempotent-Guarded

The service checks for double-submission before creating any records. If the user already has a page, the endpoint returns the existing page ID. After a successful submission, an async goroutine generates personalized agent instructions in the background.

05

Pages

Bearer JWT required. CRUD operations on the user's pages. Ownership is verified on all operations.

Endpoint Description
POST /v1/pages Create a page. Auto-generates slug from title if not provided. Creates default theme and agent config in a transaction.
GET /v1/pages List all pages for the authenticated user, ordered by created_at DESC.
GET /v1/pages/:page_id Get a single page. Requires ownership.
PUT /v1/pages/:page_id Update page. Slug changes enforced with a 30-day cooldown via slug_changed_at. Validates persona metadata.
DELETE /v1/pages/:page_id Soft-delete. Cascades to theme, agent config, documents, and chat threads.
06

Documents

Bearer JWT required. Upload and manage knowledge base files attached to a page. Max 2 documents per page, 2MB per file.

Endpoint Description
POST /v1/pages/:page_id/documents Upload a document. Multipart form with file and optional context_text. Validates MIME type (PDF, TXT, MD, CSV, DOCX), size (2MB), and count limit (2). Stores in S3-compatible storage.
GET /v1/pages/:page_id/documents List all documents for the page, ordered by created_at DESC.
GET /v1/pages/:page_id/documents/:doc_id Get a single document. Verifies it belongs to the specified page.
PATCH /v1/pages/:page_id/documents/:doc_id Update metadata. Body: {"context_text": "...", "visibility": "public|private", "is_published": true|false}.
DELETE /v1/pages/:page_id/documents/:doc_id Soft-delete from database and remove file from object storage.
07

Social Links

Bearer JWT required. Manage social and custom links displayed on the public page.

Endpoint Description
GET /v1/pages/:page_id/social-links List all social links for the page, ordered by display_order.
PUT /v1/pages/:page_id/social-links Replace all social links (PUT semantics). Body: array of {"platform": "instagram", "label": "...", "url": "..."}. Platforms: instagram, facebook, linkedin, tiktok, threads, youtube, custom.
08

Agent Configuration

Bearer JWT required. Configure the AI agent's behavior for a page.

Endpoint Description
GET /v1/pages/:page_id/agent-config Get the agent config. Includes generation_status for polling during async instruction generation.
PATCH /v1/pages/:page_id/agent-config Partial update. Fields: agent_name, greeting_message, system_prompt, personality_traits (array), model, temperature, max_tokens, focus. All optional.
09

Voice Agent Endpoints

API Key required (X-API-Key header). Used by the Python LiveKit agent to interact with the backend.

Endpoint Description
GET /v1/agent/sessions/:page_id/config Full session config: agent_name, greeting_message, system_prompt, personality_traits, model, temperature, max_tokens, page_title, page_description, documents, social_links.
GET /v1/agent/sessions/:page_id/voice-prompt Voice-specific bootstrap payload — fully composed system prompt (personalization + operating contract + KG context block), agent_name, the greeting line, full greetings_pool, model / temperature / max_tokens, and observability counters (nodes / edges loaded). Called once at session start by the LiveKit agent.
POST /v1/agent/chat/stream Stream a chat response. Body: {"page_id": "...", "turn_id": "...", "messages": [{"role": "user", "content": "..."}]}. Returns SSE stream.
POST /v1/agent/chat Non-streaming chat fallback. Same body shape, returns complete response.
POST /v1/agent/sessions/:page_id/turns Append a single voice-conversation turn (user or assistant) to the persistent chat thread. The voice agent calls this after each STT/TTS exchange so the transcript is observable in the dashboard and feeds the per-conversation history.
GET /v1/agent/sessions/:page_id/messages List the recorded turns for a given page's recent conversation. Used by the public page's voice transcript and dashboard observability.
POST /v1/agent/sessions/:page_id/finalize Mark a voice session as ended. Called when the visitor disconnects from the LiveKit room.
POST /v1/agent/knowledge/search Search the page's knowledge graph for entities and facts. Backs the agent's search_knowledge function tool — lets the LLM pull facts mid-conversation without giving up client-side audio orchestration.
09b

Billing Endpoints

Stripe subscription lifecycle. POST /v1/billing/subscribe is user-facing (Bearer JWT); POST /webhooks/stripe is Stripe-facing (signature-verified).

Endpoint Description
POST /v1/billing/subscribe Start (or resume) a 7-day Stripe trial subscription for the authenticated user. Creates the Stripe customer if missing, creates the subscription with trial_period_days=7, flips the user's plan_tier to "trial". Returns 204 on success, 409 if already on an active subscription.
POST /webhooks/stripe Stripe webhook receiver. Signature-verified via STRIPE_WEBHOOK_SECRET. Handles customer.subscription.created/updated/deleted and invoice.payment_succeeded/failed — updates the user's plan_tier based on subscription status, downgrades to "free" when the trial ends without conversion. NOTE: the route is /webhooks/stripe, not /v1/billing/webhook — configure the Stripe webhook endpoint URL accordingly.
10

Internal Endpoints

M2M secret required. Used by Auth0's Post-Login Action for user provisioning.

Endpoint Description
POST /internal/users/provision Provision a user on first login. Body: {"auth0_sub": "...", "email": "...", "name": "...", "email_verified": true, "avatar_url": "..."}. Returns: {"user_id": "uuid", "role": "user"}. Idempotent: returns existing user if already provisioned.
11

Room Token

Optional JWT. Generates a LiveKit room token for voice sessions.

Endpoint Description
POST /v1/pages/:page_id/room-token Generate a LiveKit JWT for joining a voice room. If a Bearer token is present and the caller owns the page, they join as the owner. Otherwise, they join as a visitor. The backend also dispatches the ambasdr-voice-agent to the room.
12

SSE Streaming Protocol

The chat endpoints (/v1/public/pages/:slug/chat and /v1/agent/chat/stream) return Server-Sent Events with the following event types.

Event Payload and Meaning
content Streamed text chunk from the LLM. data: {"text": "..."}. Append to the current assistant message.
thread Thread ID for conversation continuity. data: {"thread_id": "uuid"}. Store and include in the next request to maintain context.
done Stream completed. data: {}. The full assistant message has been delivered.
error Stream error. data: {"error": "message"}. The stream will close after this event.

The frontend's useAgentChat hook handles this protocol: it opens a fetch request, reads the SSE stream, appends content chunks to the active message, captures the thread ID for subsequent requests, and marks streaming as complete on the done event.

Error Responses

All non-streaming endpoints return errors in a standard format: {"error": {"code": "string", "message": "string", "request_id": "uuid"}}. HTTP status codes map to gommon's commonerrors: 400 (validation), 401 (unauthorized), 403 (forbidden), 404 (not found), 409 (conflict), 500 (internal).