{"openapi":"3.1.0","info":{"title":"EduVerse HTTP API","version":"1.0.0","summary":"Social intelligence that remembers your audience","description":"EduVerse connects Instagram, Facebook, and Threads and turns real engagement into persistent audience memory with precise posting recommendations.\n\n**When to use:** an agent should reach for this API when it needs to check service health, read or submit customer reviews, or drive Meta publishing workflows on behalf of a signed-in EduVerse account.\n\n**Onboarding:** free tier available; self-serve signup at `/signup`; zero-auth smoke tests at `/api/v1/health` and `GET /api/v1/reviews`. Rate limits: Public review submissions: 5 per minute per client. Chat: metered per session. Health: unmetered.\n\nMachine-readable companions: `/api/tools.json` (LLM function-calling definitions), `/.well-known/mcp` (Model Context Protocol server), `/.well-known/oauth-protected-resource` (RFC 9728 scope discovery), `/llms.txt` (agent guide).","contact":{"name":"EduVerse support","email":"hello@eduverse.app"},"license":{"name":"Proprietary"}},"servers":[{"url":"https://eduversesocial.vercel.app","description":"Current deployment"}],"tags":[{"name":"System","description":"Zero-auth health and capability probes."},{"name":"Reviews","description":"Public customer reviews; reads are open, writes are moderated."},{"name":"Assistant","description":"AI chat grounded in live audience analytics."},{"name":"Meta","description":"Instagram/Facebook/Threads connections, analytics, and publishing."},{"name":"Account","description":"Account lifecycle operations."}],"components":{"securitySchemes":{"sessionCookie":{"type":"apiKey","in":"cookie","name":"sb-auth-token","description":"Supabase session cookie set by /login. Used implicitly by same-origin calls."},"schedulerSecret":{"type":"http","scheme":"bearer","description":"Shared secret for the cron-only scheduler endpoint (SCHEDULER_SECRET)."}}},"security":[],"x-scopes-supported":["read:health","read:reviews","write:reviews","invoke:chat","meta:read","meta:write","account:delete"],"x-api-version":"v1","x-versioning":{"strategy":"URL path","current":"v1","stablePublicAliases":["/api/v1/health","/api/v1/reviews"],"deprecation":"Unversioned paths remain for compatibility. Future retirement will be announced here and use Deprecation and Sunset headers before removal."},"x-authentication":{"status":"session-based","note":"A separate OAuth 2.0 authorization server and self-serve API keys are not live yet. Protected operations require the EduVerse Supabase session cookie.","plannedScopes":{"read:health":"Check service health and deployment status without authentication-sensitive data.","read:reviews":"Read approved public customer reviews.","write:reviews":"Submit new customer reviews (published immediately).","invoke:chat":"Send messages to the EduVerse audience-intelligence chat assistant.","meta:read":"Read connected Meta account analytics, insights, and scheduling state.","meta:write":"Connect Meta accounts, upload media, and publish or schedule posts.","account:delete":"Permanently delete the authenticated account and its data."}},"paths":{"/api/health":{"get":{"tags":["System"],"operationId":"getHealth","summary":"Service health probe","description":"Returns service status and the current server timestamp. Zero-auth and unmetered; use it as the sandbox smoke test before calling anything else.\n\nScopes required: none (zero-auth).","security":[],"x-required-scopes":[],"responses":{"200":{"description":"JSON body: { status: \"ok\", timestamp: ISO-8601 string }.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["ok"]},"timestamp":{"type":"string","format":"date-time"}},"required":["status","timestamp"],"additionalProperties":false}}}},"429":{"description":"Rate limit exceeded; retry after the window resets.","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string"},"message":{"type":"string"},"resolution":{"type":"string"},"requestId":{"type":"string"}},"required":["type","title","status","code","message","resolution"],"additionalProperties":false}}}}}}},"/api/ai/status":{"get":{"tags":["System"],"operationId":"getAiStatus","summary":"AI provider availability","description":"Reports which AI provider and model power the chat assistant right now (provider, model, displayName). Zero-auth.\n\nScopes required: none (zero-auth).","security":[],"x-required-scopes":[],"responses":{"200":{"description":"Success with a JSON body.","content":{"application/json":{"schema":{"type":"object","properties":{"provider":{"type":"string"},"model":{"type":"string"},"displayName":{"type":"string"}},"required":["provider","model","displayName"],"additionalProperties":false}}}},"429":{"description":"Rate limit exceeded; retry after the window resets.","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string"},"message":{"type":"string"},"resolution":{"type":"string"},"requestId":{"type":"string"}},"required":["type","title","status","code","message","resolution"],"additionalProperties":false}}}}}}},"/api/reviews":{"get":{"tags":["Reviews"],"operationId":"listReviews","summary":"List approved customer reviews","description":"Returns up to 24 approved public reviews with id, name, role, rating (1-5), content, and created_at. Zero-auth; returns { reviews: [] } when storage is not configured.\n\nScopes required: none (zero-auth).","security":[],"x-required-scopes":[],"responses":{"200":{"description":"Success with a JSON body.","content":{"application/json":{"schema":{"type":"object","properties":{"reviews":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"role":{"type":"string"},"rating":{"type":"integer","minimum":1,"maximum":5},"content":{"type":"string"},"created_at":{"type":"string","format":"date-time"}},"required":["id","name","rating","content"],"additionalProperties":false}}},"required":["reviews"],"additionalProperties":false}}}}}},"post":{"tags":["Reviews"],"operationId":"createReview","summary":"Submit a customer review","description":"Submits a customer review for moderation. Reviews are stored as pending and appear only after approval. Rate limited to 5 submissions per minute per client.\n\nScopes required: none (zero-auth).","security":[],"x-required-scopes":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name","rating","content"],"properties":{"name":{"type":"string","description":"Reviewer display name.","maxLength":80},"role":{"type":"string","description":"Optional reviewer role, e.g. Social Media Manager.","maxLength":120},"rating":{"type":"integer","description":"Star rating.","minimum":1,"maximum":5},"content":{"type":"string","description":"Review text.","maxLength":800}}},"example":{"name":"Ada Lovelace","role":"Growth lead","rating":5,"content":"The posting windows are uncannily accurate."}}}},"responses":{"200":{"description":"Review submitted for moderation.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}},"required":["success","message"],"additionalProperties":false}}}},"400":{"description":"Validation failed (missing/oversized fields).","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string"},"message":{"type":"string"},"resolution":{"type":"string"},"requestId":{"type":"string"}},"required":["type","title","status","code","message","resolution"],"additionalProperties":false}}}},"429":{"description":"Rate limit exceeded; retry after the window resets.","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string"},"message":{"type":"string"},"resolution":{"type":"string"},"requestId":{"type":"string"}},"required":["type","title","status","code","message","resolution"],"additionalProperties":false}}}},"503":{"description":"Review storage unavailable.","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string"},"message":{"type":"string"},"resolution":{"type":"string"},"requestId":{"type":"string"}},"required":["type","title","status","code","message","resolution"],"additionalProperties":false}}}}}}},"/api/chat":{"post":{"tags":["Assistant"],"operationId":"sendChatMessage","summary":"Chat with the audience-intelligence assistant","description":"Sends a conversation to the EduVerse assistant grounded in the caller's live Meta analytics. Requires an authenticated session cookie. Streams plain-text chunks; ends when the model finishes.\n\nScopes required: invoke:chat.","security":[{"sessionCookie":[]}],"x-required-scopes":["invoke:chat"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["messages"],"properties":{"conversationId":{"type":"string","description":"Optional existing conversation UUID."},"messages":{"type":"array","description":"Ordered turns, oldest first. Max 20 messages of up to 8000 characters each.","items":{"type":"object","required":["role","content"],"properties":{"role":{"type":"string"},"content":{"type":"string"},"image":{"type":"string","description":"Optional base64 data-URL image attachment."}}}}}},"example":{"messages":[{"role":"user","content":"What should I post on Instagram this week?"}]}}}},"responses":{"200":{"description":"Streaming text/plain response.","content":{"text/plain":{"schema":{"type":"string","description":"Streamed assistant text."}}}},"401":{"description":"Not authenticated.","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string"},"message":{"type":"string"},"resolution":{"type":"string"},"requestId":{"type":"string"}},"required":["type","title","status","code","message","resolution"],"additionalProperties":false}}}},"429":{"description":"Rate limited.","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string"},"message":{"type":"string"},"resolution":{"type":"string"},"requestId":{"type":"string"}},"required":["type","title","status","code","message","resolution"],"additionalProperties":false}}}}}},"get":{"tags":["Assistant"],"operationId":"getChatStatus","summary":"Chat session status","description":"Returns whether the current session has an active AI-backed chat available. Requires an authenticated session cookie.\n\nScopes required: invoke:chat.","security":[{"sessionCookie":[]}],"x-required-scopes":["invoke:chat"],"responses":{"200":{"description":"Success with a JSON body.","content":{"application/json":{"schema":{"type":"object","properties":{"conversations":{"type":"array"},"messages":{"type":"array"},"conversationId":{"type":"string","format":"uuid"}},"additionalProperties":true}}}},"401":{"description":"Not authenticated.","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string"},"message":{"type":"string"},"resolution":{"type":"string"},"requestId":{"type":"string"}},"required":["type","title","status","code","message","resolution"],"additionalProperties":false}}}}}}},"/api/meta/connect":{"get":{"tags":["Meta"],"operationId":"getMetaConnection","summary":"Connected Meta accounts","description":"Returns the authenticated user's connected Instagram/Facebook/Threads connections and OAuth state. Requires an authenticated session cookie.\n\nScopes required: meta:read.","security":[{"sessionCookie":[]}],"x-required-scopes":["meta:read"],"responses":{"200":{"description":"Connection list for the signed-in account.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"live":{"type":"boolean"},"accounts":{"type":"array"}},"required":["success","accounts"],"additionalProperties":true}}}},"401":{"description":"Not authenticated.","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string"},"message":{"type":"string"},"resolution":{"type":"string"},"requestId":{"type":"string"}},"required":["type","title","status","code","message","resolution"],"additionalProperties":false}}}}}},"delete":{"tags":["Meta"],"operationId":"disconnectMetaAccount","summary":"Disconnect a Meta account","description":"Removes stored OAuth tokens for one connected platform. Requires an authenticated session cookie.\n\nScopes required: meta:write.","security":[{"sessionCookie":[]}],"x-required-scopes":["meta:write"],"parameters":[{"name":"platform","in":"query","required":true,"description":"Platform to disconnect.","schema":{"type":"string","enum":["instagram","facebook","threads"]}}],"responses":{"200":{"description":"Account disconnected.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"],"additionalProperties":false}}}},"400":{"description":"Unknown platform.","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string"},"message":{"type":"string"},"resolution":{"type":"string"},"requestId":{"type":"string"}},"required":["type","title","status","code","message","resolution"],"additionalProperties":false}}}},"401":{"description":"Not authenticated.","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string"},"message":{"type":"string"},"resolution":{"type":"string"},"requestId":{"type":"string"}},"required":["type","title","status","code","message","resolution"],"additionalProperties":false}}}}}}},"/api/meta/analytics":{"get":{"tags":["Meta"],"operationId":"getMetaAnalytics","summary":"Cross-platform engagement analytics","description":"Aggregated reach, saves, comment sentiment, and posting-window telemetry across every connected Meta account for the signed-in user. Requires an authenticated session cookie.\n\nScopes required: meta:read.","security":[{"sessionCookie":[]}],"x-required-scopes":["meta:read"],"responses":{"200":{"description":"Analytics payload keyed by platform.","content":{"application/json":{"schema":{"type":"object","properties":{"live":{"type":"boolean"},"accounts":{"type":"array"},"metrics":{"type":"object"},"recentPosts":{"type":"array"}},"required":["live"],"additionalProperties":true}}}},"401":{"description":"Not authenticated.","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string"},"message":{"type":"string"},"resolution":{"type":"string"},"requestId":{"type":"string"}},"required":["type","title","status","code","message","resolution"],"additionalProperties":false}}}}}}},"/api/meta/upload":{"post":{"tags":["Meta"],"operationId":"uploadMedia","summary":"Upload media for publishing","description":"Stores an image/video attachment for a later publish call. Accepts multipart/form-data. Requires an authenticated session cookie.\n\nScopes required: meta:write.","security":[{"sessionCookie":[]}],"x-required-scopes":["meta:write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","description":"Binary multipart part named 'file'."}}},"example":{}}}},"responses":{"200":{"description":"Media stored; returns its handle/URL.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"url":{"type":"string","format":"uri"}},"required":["success","url"],"additionalProperties":false}}}},"401":{"description":"Not authenticated.","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string"},"message":{"type":"string"},"resolution":{"type":"string"},"requestId":{"type":"string"}},"required":["type","title","status","code","message","resolution"],"additionalProperties":false}}}},"413":{"description":"File too large.","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string"},"message":{"type":"string"},"resolution":{"type":"string"},"requestId":{"type":"string"}},"required":["type","title","status","code","message","resolution"],"additionalProperties":false}}}}}}},"/api/meta/publish":{"post":{"tags":["Meta"],"operationId":"publishPost","summary":"Publish or schedule a post","description":"Publishes immediately or schedules via the official Meta Graph API to a connected account. Requires an authenticated session cookie.\n\nScopes required: meta:write.","security":[{"sessionCookie":[]}],"x-required-scopes":["meta:write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["platform"],"properties":{"platform":{"type":"string"},"caption":{"type":"string"},"scheduledAt":{"type":"string","description":"ISO-8601 timestamp for scheduled publishing."}}},"example":{"platform":"instagram","caption":"Behind the scenes of our launch","scheduledAt":"2026-08-25T15:00:00Z"}}}},"responses":{"200":{"description":"Post created or scheduled.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"platform":{"type":"string"},"postId":{"type":"string"},"status":{"type":"string"},"url":{"type":"string","format":"uri"}},"required":["success"],"additionalProperties":true}}}},"401":{"description":"Not authenticated.","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string"},"message":{"type":"string"},"resolution":{"type":"string"},"requestId":{"type":"string"}},"required":["type","title","status","code","message","resolution"],"additionalProperties":false}}}},"409":{"description":"Account not connected.","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string"},"message":{"type":"string"},"resolution":{"type":"string"},"requestId":{"type":"string"}},"required":["type","title","status","code","message","resolution"],"additionalProperties":false}}}}}}},"/api/meta/scheduler":{"patch":{"tags":["Meta"],"operationId":"runSchedulerTick","summary":"Run the scheduled-publish worker tick","description":"Cron entry point that publishes any due scheduled posts. Protected by the SCHEDULER_SECRET shared secret header, not user sessions.\n\nScopes required: meta:write.","security":[{"sessionCookie":[]}],"x-required-scopes":["meta:write"],"parameters":[{"name":"authorization","in":"header","required":true,"description":"Bearer SCHEDULER_SECRET value.","schema":{"type":"string"}}],"responses":{"200":{"description":"Tick completed.","content":{"application/json":{"schema":{"type":"object","properties":{"processed":{"type":"integer"},"succeeded":{"type":"integer"},"failed":{"type":"integer"}},"additionalProperties":true}}}},"401":{"description":"Missing or wrong secret.","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string"},"message":{"type":"string"},"resolution":{"type":"string"},"requestId":{"type":"string"}},"required":["type","title","status","code","message","resolution"],"additionalProperties":false}}}}}}},"/api/account/delete":{"delete":{"tags":["Account"],"operationId":"deleteAccount","summary":"Permanently delete the account","description":"Irreversibly deletes the signed-in account plus stored tokens, analytics cache, and workspace membership. Requires a recent authenticated session.\n\nScopes required: account:delete.","security":[{"sessionCookie":[]}],"x-required-scopes":["account:delete"],"responses":{"200":{"description":"Account deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"partial":{"type":"boolean"},"message":{"type":"string"}},"required":["success"],"additionalProperties":true}}}},"401":{"description":"Not authenticated.","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string"},"message":{"type":"string"},"resolution":{"type":"string"},"requestId":{"type":"string"}},"required":["type","title","status","code","message","resolution"],"additionalProperties":false}}}}}}}},"x-agent-usage":{"whenToUse":"Health checks, review retrieval/submission, and authenticated Meta analytics/publishing automation.","functionCallingDefinitions":"/api/tools.json","mcpServer":"/.well-known/mcp","markdownNegotiation":"Send \"Accept: text/markdown\" on any page URL to receive text/markdown.","agentGuide":"/llms.txt"}}