When you run npm run dev:all, the documentation site serves on http://localhost:3001 and proxies the Next.js API under http://localhost:3001/api. (If you run only npm run dev, use http://localhost:3000/api.)
All routes live in src/app/api/**/* and are implemented as Route Handlers using the Repository and ActionResult patterns.
sb-access-token, sb-refresh-token). Server routes call getUser() to enforce auth./admin middleware (we only expose them from the admin UI).src/app/lib/api-rate-limit.ts enforces per-route quotas:
20 requests/min per user (api-ai-chat).5 uploads/hour per user (api-ai-upload).5 sessions / 15 min per IP (api-stripe-checkout).10 uploads/hour.100 events/min per provider.Each response includes X-RateLimit-* headers when available.
| Endpoint | Method | Auth | Description |
|---|---|---|---|
/api/ai/chat | POST | Supabase session | Server-Sent Events (SSE) streaming responses from OpenAI / Gemini / Ollama via the Strategy Router with RAG + guardrails. |
/api/ai/upload | POST (multipart) | Supabase session | Uploads a document to Supabase Storage and optionally chunks + embeds it for Conversational RAG. |
/api/ai/share | POST | Supabase session | Generates a shareable tokenized URL for a conversation. |
/api/ai/chat (POST, SSE)application/json):
conversationId? (uuid)message (required string)provider? (openai, gemini, ollama)modelName?, systemPrompt?, temperature?, maxTokens?imageData? { base64, mimeType } for vision modelstext/event-stream. Every data: chunk contains { type: "delta" | "end" | "error", payload: StreamChunk }.StrategyRouter, and writes assistant messages back into Supabase.curl -N \
-H "Content-Type: application/json" \
-b "sb-access-token=..." \
-X POST http://localhost:3001/api/ai/chat \
-d '{"message":"Summarize projects","provider":"openai"}'/api/ai/upload (POST, multipart/form-data)Fields:
file – File blob (PDF, TXT, DOCX…)conversationId – Target conversation UUIDskipEmbeddings? – true to store only metadatachunkSize? – Defaults to 1000 tokenschunkStrategy? – Defaults to “recursive”Flow: validates file type/size, uploads to ai-documents bucket, persists metadata through DocumentRepository, extracts text, and (unless skipped) generates embeddings via DocumentProcessor.
/api/ai/share (POST, JSON)Body: { "conversationId": "uuid", "title?": "optional" }
Returns { success: true, shareUrl, token } where shareUrl points to /ai/shared/{token}. Tokens are base64 payloads containing conversation and user identifiers; treat them as secret and expire them when revoking shares.
| Endpoint | Method | Auth | Description |
|---|---|---|---|
/api/admin/upload-image | POST | Supabase session + admin guard | Accepts base64 media from the admin UI, stores it through the uploadImage action (Supabase Storage), and returns { success, url }. |
curl -X POST http://localhost:3001/api/admin/upload-image \
-H "Content-Type: application/json" \
-b "sb-access-token=..." \
-d '{"file":"data:image/png;base64,iVBORw0KGgo...","filename":"hero.png"}'| Endpoint | Method | Auth | Description |
|---|---|---|---|
/api/stripe/create-checkout | POST | Public (rate limited) | Creates a Stripe Checkout session for one-time purchases or subscriptions. |
/api/stripe/webhook | POST | Stripe only | Receives checkout.session.*, customer.subscription.*, and invoice.payment_* events. |
/api/stripe/create-checkoutBody:
{
"priceId": "price_123",
"isSubscription": false,
"locale": "en",
"successUrl": "https://example.com/en/loja/success",
"cancelUrl": "https://example.com/en/loja/cancelled",
"metadata": { "templateId": "landing-pro" }
}Response:
{ "sessionId": "cs_test_...", "url": "https://checkout.stripe.com/c/pay/cs_test..." }Internals: getStripeClient() creates the session, metadata is normalized via buildStripeMetadata, and payment types include both card and boleto when not subscription.
/api/stripe/webhookstripe-signature header.stripe.webhooks.constructEvent and branches on:
checkout.session.completed – mark purchases successful, revalidate caches.customer.subscription.created|updated|deleted – sync subscription state.invoice.payment_succeeded|failed – log billing telemetry.Always return 200 quickly; perform heavy work via server actions/repositories.
| Endpoint | Method | Description |
|---|---|---|
/api/resend/webhook | POST | Verifies Svix headers and logs email lifecycle events (email.sent, .delivered, .bounced, .complained, .opened, .clicked). |
Requirements:
svix-id, svix-timestamp, svix-signature.RESEND_WEBHOOK_SECRET.401 on failed verification.src/app/test/integration/api/** contains Vitest suites mocking Supabase/Stripe/Resend clients./api/ai/chat through the UI. Run npm run e2e:debug to watch SSE streaming in a real browser.cURL snippets above or tools like HTTPie/Postman against http://localhost:3001/api.Keep this reference current whenever you add or rename Route Handlers so the CLI and partners know which payloads and headers to provide.