{"openapi":"3.1.0","info":{"title":"Lune Research API","description":"Agent-platform backend (PAT / OAuth gated). See https://luneresearch.com/docs for the developer surface.","version":"1.0.0"},"paths":{"/api/v1/conferences":{"get":{"tags":["papers"],"summary":"List Conferences","description":"List all enabled conferences with paper counts and last paper date.\n\nCached for 5 min — the underlying data only churns when the crawler lands\nnew papers. A stale read here is harmless; agents already paginate forward.","operationId":"list_conferences_api_v1_conferences_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/Conference"},"type":"array","title":"Response List Conferences Api V1 Conferences Get"}}}}}}},"/api/v1/conferences/{short_name}":{"get":{"tags":["papers"],"summary":"Get Conference","description":"Get conference detail by short name.","operationId":"get_conference_api_v1_conferences__short_name__get","parameters":[{"name":"short_name","in":"path","required":true,"schema":{"type":"string","title":"Short Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Conference"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/conferences/{short_name}/papers":{"get":{"tags":["papers"],"summary":"List Conference Papers","description":"Paginated papers for a conference, optionally filtered by year/status.","operationId":"list_conference_papers_api_v1_conferences__short_name__papers_get","parameters":[{"name":"short_name","in":"path","required":true,"schema":{"type":"string","title":"Short Name"}},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Year"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaperListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/papers":{"get":{"tags":["papers"],"summary":"List Papers","description":"List papers with pagination, sorting, and optional keyword/conference filter.\n\nHidden conferences (per the caller's exclusion list) are filtered at\nthe SQL level via ``NOT IN``; absence of any exclusions means the\nplan is identical to the pre-feature query, so the new code is a\nno-op for the common case.","operationId":"list_papers_api_v1_papers_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"sort_by","in":"query","required":false,"schema":{"type":"string","default":"created_at","title":"Sort By"}},{"name":"order","in":"query","required":false,"schema":{"type":"string","pattern":"^(asc|desc)$","default":"desc","title":"Order"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Q"}},{"name":"conference","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conference"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaperListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/conferences/{short_name}/rss":{"get":{"tags":["papers"],"summary":"Get Conference Rss","description":"Return an Atom feed for a conference's most recent indexed papers.","operationId":"get_conference_rss_api_v1_conferences__short_name__rss_get","parameters":[{"name":"short_name","in":"path","required":true,"schema":{"type":"string","title":"Short Name"}},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Year"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/search/suggestions":{"get":{"tags":["search"],"summary":"Search Suggestions","description":"Fast text-match suggestions for search autocomplete (no semantic search).","operationId":"search_suggestions_api_v1_search_suggestions_get","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":100,"title":"Q"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":20,"minimum":1,"default":8,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuggestionsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/search":{"post":{"tags":["search"],"summary":"Search Papers","description":"Hybrid semantic search over papers (dense + BM25 + rerank).\n\nApplies the caller's conference-exclusion list at the SQL level in\nevery retrieval branch so excluded venues never enter the candidate\npool. Anonymous / test-harness callers (no Principal) see the full\ncorpus unchanged.","operationId":"search_papers_api_v1_search_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/papers/{paper_id}":{"get":{"tags":["search"],"summary":"Get Paper","description":"Get a single paper with authors and conference detail.\n\nCached for 5 min. Paper rows almost never change after `processing_status`\nreaches `complete`. Repeated MCP calls for the same paper hit the cache.\n\nConference exclusion intentionally does NOT apply here. Exclusion is a\n\"hide from results\" filter (search, /papers list, citations, related).\nA direct ID lookup is the caller asking for a specific paper they\nalready know about (e.g. they got the id from a citation graph, or\nwere handed it by a colleague), so we serve it without filtering.","operationId":"get_paper_api_v1_papers__paper_id__get","parameters":[{"name":"paper_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Paper Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaperResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/papers/{paper_id}/chunks":{"get":{"tags":["search"],"summary":"Get Paper Chunks","description":"Get all text chunks for a paper (for RAG context display).","operationId":"get_paper_chunks_api_v1_papers__paper_id__chunks_get","parameters":[{"name":"paper_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Paper Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PaperChunkResponse"},"title":"Response Get Paper Chunks Api V1 Papers  Paper Id  Chunks Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/papers/{paper_id}/fulltext":{"get":{"tags":["search"],"summary":"Get Paper Fulltext","description":"Return the parsed paper body, reconstructed from `paper_chunks`.\n\nThe chunk pipeline already preserves GROBID section structure, so grouping\nchunks by `section_name` gives us the same hierarchy a re-parse of\n`parsed_s3_key` would expose — without paying for an S3 round-trip.\nReturns 404 if the paper is unknown or has no chunks.","operationId":"get_paper_fulltext_api_v1_papers__paper_id__fulltext_get","parameters":[{"name":"paper_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Paper Id"}},{"name":"format","in":"query","required":false,"schema":{"enum":["markdown","json"],"type":"string","default":"markdown","title":"Format"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FullTextResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/papers/{paper_id}/citations":{"get":{"tags":["search"],"summary":"Get Paper Citations","description":"Citation graph neighbours.\n\n`direction=cites` enumerates the references parsed out of THIS paper's\nbibliography (rows in `paper_citations` keyed on `paper_id`). For\nreferences that GROBID resolved to a paper already in the corpus, we\nhydrate the full Paper record; otherwise we surface the citation row's\ndenormalised fields (title, authors, doi, year, venue).\n\n`direction=cited_by` returns Papers in our corpus whose `paper_citations`\nrows resolved to this paper — i.e. who cites it.\n\nCached for 5 min keyed on (paper_id, direction). When the caller has\nany conference exclusions the in-process cache is bypassed so each\norg gets its own filtered slice; the public-shared 5-minute window is\nonly used for the no-exclusion (cold-cache) baseline.","operationId":"get_paper_citations_api_v1_papers__paper_id__citations_get","parameters":[{"name":"paper_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Paper Id"}},{"name":"direction","in":"query","required":false,"schema":{"enum":["cited_by","cites"],"type":"string","default":"cited_by","title":"Direction"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CitationsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/papers/{paper_id}/related":{"get":{"tags":["search"],"summary":"Get Related Papers","description":"Return papers with the most similar embeddings (cosine distance via pgvector).\n\nHonors the caller's conference exclusion list: hidden venues are\nfiltered out at the SQL level so the HNSW post-filter never burns\ncandidates on rows that will be discarded.","operationId":"get_related_papers_api_v1_papers__paper_id__related_get","parameters":[{"name":"paper_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Paper Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":20,"minimum":1,"default":6,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PaperResponse"},"title":"Response Get Related Papers Api V1 Papers  Paper Id  Related Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/research-guidance":{"get":{"tags":["research-guidance"],"summary":"List Guidance Docs","operationId":"list_guidance_docs_api_v1_research_guidance_get","parameters":[{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Guidance Docs Api V1 Research Guidance Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/research-guidance/{doc_id}":{"get":{"tags":["research-guidance"],"summary":"Get Guidance Doc","operationId":"get_guidance_doc_api_v1_research_guidance__doc_id__get","parameters":[{"name":"doc_id","in":"path","required":true,"schema":{"type":"string","title":"Doc Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Guidance Doc Api V1 Research Guidance  Doc Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/research-guidance/search":{"post":{"tags":["research-guidance"],"summary":"Search Guidance","description":"Top-K nearest guidance chunks for `query`.\n\nVector search via Cohere v4 + pgvector cosine similarity is preferred.\nWhen the embedding provider is unavailable or no chunks have populated\nembeddings yet, transparently falls back to a Postgres tsvector FTS query\nso callers always receive a uniformly-shaped result with a `score` field.","operationId":"search_guidance_api_v1_research_guidance_search_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuidanceSearchRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuidanceSearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/subscriptions":{"get":{"tags":["subscriptions"],"summary":"List Subscriptions","description":"List all subscriptions for the calling org.","operationId":"list_subscriptions_api_v1_subscriptions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/Subscription"},"type":"array","title":"Response List Subscriptions Api V1 Subscriptions Get"}}}}}},"post":{"tags":["subscriptions"],"summary":"Create Subscription","description":"Subscribe the current org to a conference. Idempotent on (org, conf).","operationId":"create_subscription_api_v1_subscriptions_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Subscription"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/subscriptions/{subscription_id}":{"delete":{"tags":["subscriptions"],"summary":"Delete Subscription","description":"Delete a subscription. Any member of the owning org can do this.\n\nUses raw SQL rather than `db.delete(orm_obj)` because the ORM expansion\nwalks the FK chain and tries to resolve `orgs.id` - and there's no\nregistered Org SQLAlchemy model in this codebase, so the flush fails\nwith `NoReferencedTableError`. Raw SQL keeps the delete physical and\navoids that entire codepath.","operationId":"delete_subscription_api_v1_subscriptions__subscription_id__delete","parameters":[{"name":"subscription_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Subscription Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/notifications/read-all":{"patch":{"tags":["subscriptions"],"summary":"Mark All Notifications Read","description":"Mark all unread notifications as read for the calling org.","operationId":"mark_all_notifications_read_api_v1_notifications_read_all_patch","responses":{"204":{"description":"Successful Response"}}}},"/api/v1/notifications/{notification_id}/read":{"patch":{"tags":["subscriptions"],"summary":"Mark Notification Read","description":"Mark a single notification as read. 404 if it belongs to another org.","operationId":"mark_notification_read_api_v1_notifications__notification_id__read_patch","parameters":[{"name":"notification_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Notification Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/subscriptions/{subscription_id}/drain":{"get":{"tags":["subscriptions"],"summary":"Drain Subscription","description":"Pull papers indexed for this subscription's conference since the cursor.\n\nCursor format: opaque url-safe-base64 of `{v:1, last_id, last_at}`. Pass\nthe previous response's `next_cursor` verbatim to resume; omit for first\npage (resumes from the subscription's `created_at`).\n\nAuth: subscription.org_id must match `principal.org_id`. 403 otherwise.","operationId":"drain_subscription_api_v1_subscriptions__subscription_id__drain_get","parameters":[{"name":"subscription_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Subscription Id"}},{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Since"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DrainResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/notifications":{"get":{"tags":["subscriptions"],"summary":"List Notifications","description":"Paginated notifications for the calling org.","operationId":"list_notifications_api_v1_notifications_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/conference-exclusions":{"get":{"tags":["conference-exclusions"],"summary":"List Exclusions","description":"Return every conference this org has hidden.","operationId":"list_exclusions_api_v1_conference_exclusions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ConferenceExclusion"},"type":"array","title":"Response List Exclusions Api V1 Conference Exclusions Get"}}}}}},"post":{"tags":["conference-exclusions"],"summary":"Create Exclusion","description":"Hide ``conference_id`` from every paper-returning route for this org.\n\nIdempotent on ``(org_id, conference_id)``: re-posting the same body\nreturns the existing row.","operationId":"create_exclusion_api_v1_conference_exclusions_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConferenceExclusionCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConferenceExclusion"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/conference-exclusions/{exclusion_id}":{"delete":{"tags":["conference-exclusions"],"summary":"Delete Exclusion","description":"Restore a hidden conference. Raw SQL (see the subscriptions router\nfor the rationale: ORM cascade walks an unregistered ``orgs`` FK that\nflush refuses to resolve, even though the row deletes cleanly via SQL).","operationId":"delete_exclusion_api_v1_conference_exclusions__exclusion_id__delete","parameters":[{"name":"exclusion_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Exclusion Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/account/whoami":{"get":{"tags":["account"],"summary":"Whoami","description":"Snapshot of the active org's tier, quota, credits, subscription state.\n\nOptional `?org_slug=…` parameter overrides the default (the principal's\nbootstrap org, which is always personal for Supabase JWTs). The\ndashboard's `useActiveOrg().slug` is sent on every whoami fetch so that\nswitching the active team in the sidebar OrgSwitcher actually changes\nthe rendered tier/credits/billing state - without this override every\norg-switch left whoami stuck on the personal org's data.\n\nMembership is enforced: the principal must be a member of `org_slug`\n(any role). Otherwise 403, so a malformed/altered localStorage value\ncan't read another org's state.","operationId":"whoami_api_v1_account_whoami_get","parameters":[{"name":"org_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Org Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhoAmIOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/account":{"delete":{"tags":["account"],"summary":"Delete Account","description":"Soft-delete the authenticated user's account.\n\nRequires `?confirm=true` to guard against accidental deletion. Best-effort:\n  1. Cancel Stripe subscriptions for orgs the user owns alone.\n  2. Revoke all PATs created by this user.\n  3. Revoke all OAuth refresh tokens for this user.\n  4. Drop org_memberships for this user (CASCADE follows from auth.users\n     hard-delete in 30 days).\n  5. Mark `raw_user_meta_data.lune_deleted_at` so a nightly purge job\n     can finalise hard deletion after the 30-day grace window.\n  6. Audit-log the deletion.\n\nStripe failures are logged but never block the deletion.","operationId":"delete_account_api_v1_account_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"confirm","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Confirm"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteAccountOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/account/usage/daily":{"get":{"tags":["account"],"summary":"Usage Daily","operationId":"usage_daily_api_v1_account_usage_daily_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/DailyUsageRow"},"type":"array","title":"Response Usage Daily Api V1 Account Usage Daily Get"}}}}}}},"/api/v1/orgs/{org_slug}/keys":{"post":{"tags":["api_keys"],"summary":"Create Key","description":"Mint a PAT for the calling user against this org.\n\nOpen to every member - a PAT is a personal credential and a member\non a paid team needs their own to use the CLI/MCP against the team's\nshared quota.","operationId":"create_key_api_v1_orgs__org_slug__keys_post","parameters":[{"name":"org_slug","in":"path","required":true,"schema":{"type":"string","title":"Org Slug"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateKeyIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateKeyOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["api_keys"],"summary":"List Keys","description":"List the org's PATs, scoped by role.\n\nAdmins/owners see every key in the org for audit / offboarding. Plain\nmembers see only the keys they minted themselves - there's no reason\na peer member needs visibility into someone else's machine token.","operationId":"list_keys_api_v1_orgs__org_slug__keys_get","parameters":[{"name":"org_slug","in":"path","required":true,"schema":{"type":"string","title":"Org Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/KeyOut"},"title":"Response List Keys Api V1 Orgs  Org Slug  Keys Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/orgs/{org_slug}/keys/{key_id}":{"delete":{"tags":["api_keys"],"summary":"Revoke Key","description":"Revoke a key, scoped by role.\n\nAdmins/owners can revoke any key in the org (offboarding / compromise\nresponse). Members can only revoke keys they minted themselves -\nrevoking a teammate's key would let one member kick another off the\nCLI/MCP without an admin in the loop.","operationId":"revoke_key_api_v1_orgs__org_slug__keys__key_id__delete","parameters":[{"name":"org_slug","in":"path","required":true,"schema":{"type":"string","title":"Org Slug"}},{"name":"key_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Key Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/orgs":{"get":{"tags":["orgs"],"summary":"List Orgs","operationId":"list_orgs_api_v1_orgs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/OrgListItem"},"type":"array","title":"Response List Orgs Api V1 Orgs Get"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["orgs"],"summary":"Create Org","operationId":"create_org_api_v1_orgs_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOrgIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOrgOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/orgs/{slug}":{"get":{"tags":["orgs"],"summary":"Get Org","operationId":"get_org_api_v1_orgs__slug__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["orgs"],"summary":"Update Org","operationId":"update_org_api_v1_orgs__slug__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateOrgIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["orgs"],"summary":"Delete Org","operationId":"delete_org_api_v1_orgs__slug__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/orgs/{slug}/members":{"post":{"tags":["orgs"],"summary":"Invite Member","operationId":"invite_member_api_v1_orgs__slug__members_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteMemberIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Invite Member Api V1 Orgs  Slug  Members Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/orgs/{slug}/members/{user_id}":{"delete":{"tags":["orgs"],"summary":"Remove Member","operationId":"remove_member_api_v1_orgs__slug__members__user_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["orgs"],"summary":"Change Member Role","description":"Change a member's role between 'member' and 'admin'. Owner-only.\n\nOwners can't be demoted via this endpoint - use /transfer-ownership first.","operationId":"change_member_role_api_v1_orgs__slug__members__user_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeRoleIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/orgs/{slug}/transfer-ownership":{"post":{"tags":["orgs"],"summary":"Transfer Ownership","description":"Transfer the owner role to another existing member. The current owner\nis demoted to 'admin' atomically so the org never has zero owners.\n\nPersonal orgs can't transfer ownership (each user has exactly one).","operationId":"transfer_ownership_api_v1_orgs__slug__transfer_ownership_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferOwnershipIn"}}}},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/orgs/{slug}/invitations":{"post":{"tags":["orgs"],"summary":"Create Invitation","description":"Generate a single-use signup token. Owner can grant any role; admin can\ngrant only 'member'. Personal orgs cannot have additional members.","operationId":"create_invitation_api_v1_orgs__slug__invitations_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInvitationIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvitationOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["orgs"],"summary":"List Invitations","description":"Active (unaccepted, non-revoked, unexpired) invitations for the org.","operationId":"list_invitations_api_v1_orgs__slug__invitations_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/InvitationListItem"},"title":"Response List Invitations Api V1 Orgs  Slug  Invitations Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/orgs/{slug}/invitations/{invitation_id}":{"delete":{"tags":["orgs"],"summary":"Revoke Invitation","operationId":"revoke_invitation_api_v1_orgs__slug__invitations__invitation_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"invitation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Invitation Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/invitations/{token}":{"get":{"tags":["orgs"],"summary":"Peek Invitation","description":"Public endpoint - returns just enough metadata for the /invite/[token]\npage to render before the user signs in. Does NOT reveal the inviter or\nmembership state.","operationId":"peek_invitation_api_v1_invitations__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvitationPeek"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/invitations/{token}/accept":{"post":{"tags":["orgs"],"summary":"Accept Invitation","description":"Atomically: lookup invitation, ensure user's email matches (case-insensitive),\ninsert org_memberships, mark invitation accepted_at.","operationId":"accept_invitation_api_v1_invitations__token__accept_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptInvitationOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/oauth/register":{"post":{"tags":["oauth"],"summary":"Dcr","operationId":"dcr_oauth_register_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DcrIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/oauth/authorize":{"get":{"tags":["oauth"],"summary":"Authorize","operationId":"authorize_oauth_authorize_get","parameters":[{"name":"client_id","in":"query","required":true,"schema":{"type":"string","title":"Client Id"}},{"name":"redirect_uri","in":"query","required":true,"schema":{"type":"string","title":"Redirect Uri"}},{"name":"response_type","in":"query","required":true,"schema":{"type":"string","title":"Response Type"}},{"name":"scope","in":"query","required":true,"schema":{"type":"string","title":"Scope"}},{"name":"state","in":"query","required":true,"schema":{"type":"string","title":"State"}},{"name":"code_challenge","in":"query","required":true,"schema":{"type":"string","title":"Code Challenge"}},{"name":"code_challenge_method","in":"query","required":true,"schema":{"type":"string","title":"Code Challenge Method"}},{"name":"resource","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resource"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/oauth/authorize/consent":{"post":{"tags":["oauth"],"summary":"Consent","description":"Mint an authorization code (or deny) and tell the caller where to go next.\n\nThe redirect_uri is typically the CLI's local one-shot callback server\n(http://127.0.0.1:13373/callback) which closes after capturing one request.\nReturning a 302 from this endpoint and having the browser-side fetch follow\nit would cause the callback URL to be hit *twice* - once by fetch, once\nby the subsequent window.location navigation - and the second request\narrives after the CLI has already shut down (→ \"Failed to fetch\").\n\nTo keep the browser navigation single-shot, we return:\n  * 200 + JSON { redirect_url } when the request asks for JSON\n    (the dashboard consent page does, via Accept: application/json).\n  * 302 + Location header for everything else (e.g. direct curl, tests).","operationId":"consent_oauth_authorize_consent_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConsentIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/oauth/token":{"post":{"tags":["oauth"],"summary":"Token","operationId":"token_oauth_token_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_token_oauth_token_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/oauth/revoke":{"post":{"tags":["oauth"],"summary":"Revoke","operationId":"revoke_oauth_revoke_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_revoke_oauth_revoke_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/oauth/userinfo":{"get":{"tags":["oauth"],"summary":"Userinfo","operationId":"userinfo_oauth_userinfo_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/oauth-authorization-server":{"get":{"tags":["oauth"],"summary":"Metadata","operationId":"metadata__well_known_oauth_authorization_server_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/openid-configuration":{"get":{"tags":["oauth"],"summary":"Oidc Metadata","operationId":"oidc_metadata__well_known_openid_configuration_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/oauth-protected-resource":{"get":{"tags":["oauth"],"summary":"Protected Resource Metadata","operationId":"protected_resource_metadata__well_known_oauth_protected_resource_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/jwks.json":{"get":{"tags":["oauth"],"summary":"Jwks","operationId":"jwks__well_known_jwks_json_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/auth/me":{"get":{"tags":["auth"],"summary":"Get Me","description":"Return authenticated user info from Supabase JWT.","operationId":"get_me_api_v1_auth_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Me Api V1 Auth Me Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/billing/checkout":{"post":{"tags":["billing"],"summary":"Start Checkout","operationId":"start_checkout_api_v1_billing_checkout_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/billing/credits/checkout":{"post":{"tags":["billing"],"summary":"Start Credits Checkout","description":"Open a Stripe Checkout (mode=payment) for one $0.99 / 300-credit pack.\n\nAny org member can buy credits - overage spend isn't restricted to owners\nthe way subscription changes are. The webhook (`checkout.session.completed`,\nmode=payment) idempotently increments `credit_balances.credits_remaining`\non the org keyed by `client_reference_id`.","operationId":"start_credits_checkout_api_v1_billing_credits_checkout_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditCheckoutIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/billing/checkout/sync":{"get":{"tags":["billing"],"summary":"Sync Checkout","description":"Pull a completed Checkout Session from Stripe and apply the same DB\nwrites the webhook would.\n\nBelt-and-suspenders for two scenarios:\n  1. Local dev without `stripe listen` forwarding events to localhost.\n  2. Prod webhook delivery delay (Stripe retries can be minutes apart).\n\nIdempotent: subscription + credit-pack writes both use UNIQUE/UPSERT\nconstraints, so if the webhook already applied, this returns\n`applied=False` and changes nothing.","operationId":"sync_checkout_api_v1_billing_checkout_sync_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"query","required":true,"schema":{"type":"string","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutSyncOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/billing/change-tier":{"post":{"tags":["billing"],"summary":"Change Tier","description":"Change subscription tier in-flight.\n\nTransitions:\n  - free → pro/max:  409, must use /checkout (no existing customer)\n  - pro/max → free:  cancels Stripe subscription at period end (Customer\n                     Portal-style). Any pending schedule is released first\n                     so the cancel takes precedence.\n  - max → pro:       deferred via Stripe Subscription Schedule; user keeps\n                     Max benefits until period end, then transitions to\n                     Pro automatically. Persisted locally as\n                     `pending_tier='pro'` for the dashboard banner.\n  - pro → max:       immediate, with proration (upgrades land in-cycle).","operationId":"change_tier_api_v1_billing_change_tier_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeTierIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Change Tier Api V1 Billing Change Tier Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/billing/resume":{"post":{"tags":["billing"],"summary":"Resume Subscription","description":"Undo whichever pending change the user has scheduled.\n\nTwo flavours of \"pending\":\n  • `cancel_at_period_end=true`        → user previously cancelled.\n  • `pending_tier` + `stripe_schedule_id` → user previously downgraded.\n\nEither way, the user changed their mind and wants their current tier\nto keep going as-is. We unwind the appropriate Stripe state and clear\nthe local mirrors so the dashboard banner disappears on next render.","operationId":"resume_subscription_api_v1_billing_resume_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResumeIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Resume Subscription Api V1 Billing Resume Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/billing/portal":{"post":{"tags":["billing"],"summary":"Open Portal","operationId":"open_portal_api_v1_billing_portal_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortalIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortalOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/webhooks/stripe":{"post":{"tags":["webhooks"],"summary":"Stripe Webhook","operationId":"stripe_webhook_webhooks_stripe_post","parameters":[{"name":"stripe-signature","in":"header","required":true,"schema":{"type":"string","title":"Stripe-Signature"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Stripe Webhook Webhooks Stripe Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dev/daily":{"post":{"tags":["dev"],"summary":"Set Daily Counter","description":"Set today's DynamoDB daily counter for Pro/Max.\n\n`quota.check_and_increment` reads/increments `daily#{org_id}#{today}`. To\ntest the \"daily quota exhausted → dip into credits\" path on Pro/Max,\nbump this to `_TIER_DAILY_CAP[tier]` (300 for pro, 600 for max). Free\ntier orgs don't have a daily counter - the endpoint is a no-op for them\naside from confirming the org membership.","operationId":"set_daily_counter_api_v1_dev_daily_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevDailyIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevDailyOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/dev/credits":{"post":{"tags":["dev"],"summary":"Set Credits","description":"Force `credit_balances.credits_remaining` to a specific value.\n\nSkips the Stripe Checkout dance entirely so you can exercise the\nin-balance / out-of-credits paths without spending. Doesn't bump\n`credits_purchased` (lifetime audit), so don't use this to fake history.","operationId":"set_credits_api_v1_dev_credits_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevCreditsIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevCreditsOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/dev/tier":{"post":{"tags":["dev"],"summary":"Set Tier","description":"Flip the org's tier and re-size its current-period included_units.\n\nSkips Stripe entirely - `stripe_customer_id` and `stripe_subscription_id`\non the org are NOT touched, so subsequent real upgrades still work.","operationId":"set_tier_api_v1_dev_tier_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevTierIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevTierOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/dev/subscription":{"post":{"tags":["dev"],"summary":"Seed Subscription","description":"Upsert a `billing_subscriptions` row for the test org without a real\nStripe subscription. Cypress drives the cancel-banner / resume / out-of-\ncredits paths through this so the suite never needs live Stripe state.","operationId":"seed_subscription_api_v1_dev_subscription_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevSubscriptionIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevSubscriptionOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/dev/mcp-tools":{"get":{"tags":["dev"],"summary":"List Mcp Tools","description":"Catalog of every MCP tool exposed by `@lune/mcp-server`.\n\nThe dashboard renders one form per tool from this. Reuses the same\ncatalog the admin test bed uses so behavior stays in lockstep.","operationId":"list_mcp_tools_api_v1_dev_mcp_tools_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/McpToolSchema"},"type":"array","title":"Response List Mcp Tools Api V1 Dev Mcp Tools Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/dev/mcp-tools/test-pat":{"post":{"tags":["dev"],"summary":"Mint Mcp Tester Pat","description":"Mint a 10-minute PAT for the dashboard MCP tester.\n\nThe browser uses this PAT for every tool call so requests flow through the\nfull agent path (AuthMiddleware → RateLimit → Usage with `auth_method=PAT`,\nbillable=True). Daily counter increments, credits drain on excess, etc.\nWithout this, the tester would auth via Supabase JWT (non-billable) and\nbypass the very behavior the user is trying to verify.","operationId":"mint_mcp_tester_pat_api_v1_dev_mcp_tools_test_pat_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestPatIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestPatOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/admin/login":{"get":{"tags":["admin"],"summary":"Admin Login Page","operationId":"admin_login_page_admin_login_get","parameters":[{"name":"next","in":"query","required":false,"schema":{"type":"string","default":"/admin/dashboard","title":"Next"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["admin"],"summary":"Admin Login","operationId":"admin_login_admin_login_post","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_admin_login_admin_login_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/logout":{"get":{"tags":["admin"],"summary":"Admin Logout","operationId":"admin_logout_admin_logout_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/":{"get":{"tags":["admin"],"summary":"Admin Root","operationId":"admin_root_admin__get","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"307":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/dashboard":{"get":{"tags":["admin"],"summary":"Admin Dashboard","operationId":"admin_dashboard_admin_dashboard_get","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/dashboard/stats":{"get":{"tags":["admin"],"summary":"Admin Dashboard Stats","description":"JSON endpoint for real-time dashboard polling (called every 5 s by JS).","operationId":"admin_dashboard_stats_admin_dashboard_stats_get","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Dashboard Stats Admin Dashboard Stats Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/conferences":{"get":{"tags":["admin"],"summary":"Admin List Conferences","operationId":"admin_list_conferences_admin_conferences_get","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["admin"],"summary":"Admin Create Conference","operationId":"admin_create_conference_admin_conferences_post","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"},"title":"Response Admin Create Conference Admin Conferences Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/conferences/preview-crawl":{"post":{"tags":["admin"],"summary":"Admin Preview Crawl","description":"Run a limited test crawl (up to 10 papers) to validate source config before saving.","operationId":"admin_preview_crawl_admin_conferences_preview_crawl_post","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Preview Crawl Admin Conferences Preview Crawl Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/conferences/{conf_id}":{"put":{"tags":["admin"],"summary":"Admin Update Conference","operationId":"admin_update_conference_admin_conferences__conf_id__put","parameters":[{"name":"conf_id","in":"path","required":true,"schema":{"type":"string","title":"Conf Id"}},{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Update Conference Admin Conferences  Conf Id  Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["admin"],"summary":"Admin Delete Conference","operationId":"admin_delete_conference_admin_conferences__conf_id__delete","parameters":[{"name":"conf_id","in":"path","required":true,"schema":{"type":"string","title":"Conf Id"}},{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/conferences/{conf_id}/nuke":{"post":{"tags":["admin"],"summary":"Admin Nuke Conference Papers","description":"Delete all papers, chunks, citations, crawl jobs, and S3 assets for a conference.\n\nThe conference record itself is kept intact. This is intended for re-crawling from scratch.","operationId":"admin_nuke_conference_papers_admin_conferences__conf_id__nuke_post","parameters":[{"name":"conf_id","in":"path","required":true,"schema":{"type":"string","title":"Conf Id"}},{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Nuke Conference Papers Admin Conferences  Conf Id  Nuke Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/conferences/{conf_id}/crawl":{"post":{"tags":["admin"],"summary":"Admin Trigger Crawl","description":"Enqueue a crawl job for each configured year of this conference.","operationId":"admin_trigger_crawl_admin_conferences__conf_id__crawl_post","parameters":[{"name":"conf_id","in":"path","required":true,"schema":{"type":"string","title":"Conf Id"}},{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Trigger Crawl Admin Conferences  Conf Id  Crawl Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/conferences/{conf_id}/test-crawl":{"post":{"tags":["admin"],"summary":"Admin Test Crawl","description":"Crawl one paper from this conference and run it through the full inline pipeline.\n\nUseful for verifying the entire stack (crawl → PDF → parse → enrich → embed) works\nend-to-end before triggering a full crawl.  The paper is upserted to the DB, then the\npipeline runs as a background task - track progress in the Papers view.","operationId":"admin_test_crawl_admin_conferences__conf_id__test_crawl_post","parameters":[{"name":"conf_id","in":"path","required":true,"schema":{"type":"string","title":"Conf Id"}},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Year"}},{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Test Crawl Admin Conferences  Conf Id  Test Crawl Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/papers":{"get":{"tags":["admin"],"summary":"Admin List Papers","operationId":"admin_list_papers_admin_papers_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","default":"","title":"Status"}},{"name":"conference_filter","in":"query","required":false,"schema":{"type":"string","default":"","title":"Conference Filter"}},{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/papers/{paper_id}/status":{"get":{"tags":["admin"],"summary":"Admin Paper Status","operationId":"admin_paper_status_admin_papers__paper_id__status_get","parameters":[{"name":"paper_id","in":"path","required":true,"schema":{"type":"string","title":"Paper Id"}},{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Paper Status Admin Papers  Paper Id  Status Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/papers/{paper_id}/reprocess":{"post":{"tags":["admin"],"summary":"Admin Reprocess Paper","description":"Re-enrich from OpenAlex, reset to 'pending', then run the full pipeline.\n\nMirrors the crawling pipeline: OpenAlex enrichment (abstract, citation_count,\narxiv_id, oa_pdf_url) → PDF discovery → parse → AI enrich → embed.","operationId":"admin_reprocess_paper_admin_papers__paper_id__reprocess_post","parameters":[{"name":"paper_id","in":"path","required":true,"schema":{"type":"string","title":"Paper Id"}},{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/papers/requeue-no-pdf":{"post":{"tags":["admin"],"summary":"Admin Requeue No Pdf Papers","description":"Re-enqueue abstract-only papers to the PDF queue for a fresh discovery attempt.\n\nTargets papers with processing_status='abstract_indexed' so the new resolver chain\n(arXiv → IACR → Brave Search) can find PDFs that were previously missed.\nResets status to 'pending' and sends each paper to the SQS PDF queue (or runs\ninline if SQS is not configured).","operationId":"admin_requeue_no_pdf_papers_admin_papers_requeue_no_pdf_post","parameters":[{"name":"conference_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conference Id"}},{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Requeue No Pdf Papers Admin Papers Requeue No Pdf Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/papers/{paper_id}":{"delete":{"tags":["admin"],"summary":"Admin Delete Paper","operationId":"admin_delete_paper_admin_papers__paper_id__delete","parameters":[{"name":"paper_id","in":"path","required":true,"schema":{"type":"string","title":"Paper Id"}},{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/embed/batch-transform/start":{"post":{"tags":["admin"],"summary":"Admin Embed Batch Transform Start","description":"Drain the embed queue and submit a SageMaker batch-transform job.\n\nReturns immediately with the prospective job name; the heavy work\n(drain SQS, chunk papers, upload to S3, create-transform-job) runs in\na detached background task so the click doesn't tie up an ALB request\nslot for ~30 s on a multi-thousand-message backlog. The task is held\nby ``_BACKGROUND_TASKS`` so the GC can't reap it before it finishes.\n\nEmpty queue → returns the synthetic job name immediately, but the\nbackground runner logs \"embed queue empty\" and no SageMaker job is\ncreated. Configuration miss (no S3 / no model) → background runner\nlogs a structured error; the response itself still 200s because the\nrequest just *schedules* the work.","operationId":"admin_embed_batch_transform_start_admin_embed_batch_transform_start_post","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Embed Batch Transform Start Admin Embed Batch Transform Start Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/embed/requeue-stuck":{"post":{"tags":["admin"],"summary":"Admin Embed Requeue Stuck","description":"Re-enqueue papers stuck in non-terminal embed states back to the queue.\n\nRescue endpoint for cases where SQS messages were deleted but never\nprocessed - most commonly when an earlier batch-transform click had\nits background task GC'd before it could create the SageMaker job\n(the bug the strong-reference set above prevents going forward, but\nthat already lost messages we need to recover).\n\nPulls papers whose ``processing_status`` is in the set\n``{ocr_complete, abstract_embedding, pdf_downloaded, enriched}`` and\nsends a fresh SQS message for each. The live EmbedWorker (or another\nbatch-transform click) will pick them up. Idempotent - re-running\nre-enqueues the same papers; the consumer's upsert is a no-op when\nthe paper has already advanced to a terminal state.","operationId":"admin_embed_requeue_stuck_admin_embed_requeue_stuck_post","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50000,"minimum":1,"default":5000,"title":"Limit"}},{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Embed Requeue Stuck Admin Embed Requeue Stuck Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/embed/batch-transform":{"get":{"tags":["admin"],"summary":"Admin Embed Batch Transform List","description":"List the most recent SageMaker batch transform jobs (Lune-tagged).\n\nUsed by the dashboard to render the \"active / recent batch jobs\" panel\nafter a click on the start button.","operationId":"admin_embed_batch_transform_list_admin_embed_batch_transform_get","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Embed Batch Transform List Admin Embed Batch Transform Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/embed/batch-transform/{job_name}/ingest":{"post":{"tags":["admin"],"summary":"Admin Embed Batch Transform Ingest","description":"Ingest the output of a completed batch-transform job into Postgres.\n\nIdempotent - re-running on an already-ingested job re-upserts the\nchunk rows with the same vectors. Safe to retry. Returns\n``status=Completed`` (i.e. SageMaker is still running) or\n``status=ingested`` with paper / chunk counts on success.","operationId":"admin_embed_batch_transform_ingest_admin_embed_batch_transform__job_name__ingest_post","parameters":[{"name":"job_name","in":"path","required":true,"schema":{"type":"string","title":"Job Name"}},{"name":"drop_index","in":"query","required":false,"schema":{"type":"boolean","description":"Drop the chunks HNSW index before the bulk insert and rebuild concurrently after. Recommended for backfills of >5k papers; search latency degrades to seq-scan during the rebuild window.","default":false,"title":"Drop Index"},"description":"Drop the chunks HNSW index before the bulk insert and rebuild concurrently after. Recommended for backfills of >5k papers; search latency degrades to seq-scan during the rebuild window."},{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Embed Batch Transform Ingest Admin Embed Batch Transform  Job Name  Ingest Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/embed/realtime-endpoint":{"get":{"tags":["admin"],"summary":"Admin Realtime Endpoint Status","description":"Live state for the dashboard's realtime-endpoint card.\n\nReturns ``exists=False`` when the endpoint hasn't been launched yet,\nplus the configured instance type so the UI can render the launch\nbutton with the correct cost estimate.","operationId":"admin_realtime_endpoint_status_admin_embed_realtime_endpoint_get","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Realtime Endpoint Status Admin Embed Realtime Endpoint Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/embed/realtime-endpoint/start":{"post":{"tags":["admin"],"summary":"Admin Realtime Endpoint Start","description":"Provision endpoint config + endpoint, then register autoscaling once\nInService.\n\nIdempotent - a second click while the endpoint exists returns the\ncurrent state without re-creating. Always re-spawns the autoscaling\nbackground task so a stuck/missing scalable target self-heals on the\nnext click.\n\nEagerly invalidates the embed provider's state cache so the next\nembed call sees the new endpoint within milliseconds rather than\nwaiting on the 30 s TTL.","operationId":"admin_realtime_endpoint_start_admin_embed_realtime_endpoint_start_post","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Realtime Endpoint Start Admin Embed Realtime Endpoint Start Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/embed/realtime-endpoint/stop":{"post":{"tags":["admin"],"summary":"Admin Realtime Endpoint Stop","description":"Tear down the endpoint, its config, and the autoscaling target.\n\nEmbedWorker continues servicing the queue immediately via the Cohere\ndirect → Bedrock fallback chain. The state cache is invalidated so\nthe next embed call doesn't waste a round-trip on a dead endpoint.","operationId":"admin_realtime_endpoint_stop_admin_embed_realtime_endpoint_stop_post","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Realtime Endpoint Stop Admin Embed Realtime Endpoint Stop Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/dev/bench-pat":{"post":{"tags":["admin"],"summary":"Admin Mint Bench Pat","description":"Mint a benchmark PAT - bypasses L1 + L2 rate-limits and billing.\n\nAdmin-only. Returns the plaintext token ONCE - store it locally;\nthere's no recovery if lost. Use it as a Bearer token against any\nPAT-authenticated endpoint to drive synthetic load tests without\ncontending with real users or polluting org-level billing meters.\n\nRevoke via ``UPDATE lune_api_keys SET revoked_at = NOW() WHERE\nid = '<id>'`` or by setting ``is_benchmark = FALSE`` (which downgrades\nit to a normal PAT subject to rate limits).","operationId":"admin_mint_bench_pat_admin_dev_bench_pat_post","parameters":[{"name":"name","in":"query","required":false,"schema":{"type":"string","description":"Label that ends up in lune_api_keys.name for audit","default":"benchmark","title":"Name"},"description":"Label that ends up in lune_api_keys.name for audit"},{"name":"org_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Org to mint under. Defaults to the first 'max'-tier org the system finds; the load test's org_id will surface in audit + usage events but quota / billing is bypassed for this PAT regardless.","title":"Org Slug"},"description":"Org to mint under. Defaults to the first 'max'-tier org the system finds; the load test's org_id will surface in audit + usage events but quota / billing is bypassed for this PAT regardless."},{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Mint Bench Pat Admin Dev Bench Pat Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/notifications/dispatch":{"post":{"tags":["admin"],"summary":"Admin Dispatch Notifications","description":"Manually trigger daily notification dispatch (normally run by EventBridge cron).","operationId":"admin_dispatch_notifications_admin_notifications_dispatch_post","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Dispatch Notifications Admin Notifications Dispatch Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/dlq":{"get":{"tags":["admin"],"summary":"Admin Dlq","description":"Dead Letter Queue viewer - reads all DLQ queues (lune-*Dlq*).","operationId":"admin_dlq_admin_dlq_get","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/playground":{"get":{"tags":["admin"],"summary":"Admin Playground","description":"API playground for post-deploy endpoint verification.","operationId":"admin_playground_admin_playground_get","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/playground/test-token":{"get":{"tags":["admin"],"summary":"Admin Playground Test Token","description":"Fetch a Supabase JWT for the configured test user.","operationId":"admin_playground_test_token_admin_playground_test_token_get","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"},"title":"Response Admin Playground Test Token Admin Playground Test Token Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/research-guidance":{"get":{"tags":["admin"],"summary":"Admin Guidance List","operationId":"admin_guidance_list_admin_research_guidance_get","parameters":[{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"msg","in":"query","required":false,"schema":{"type":"string","default":"","title":"Msg"}},{"name":"msg_type","in":"query","required":false,"schema":{"type":"string","default":"success","title":"Msg Type"}},{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["admin"],"summary":"Admin Guidance Ingest","operationId":"admin_guidance_ingest_admin_research_guidance_post","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/research-guidance/{document_id}/delete":{"post":{"tags":["admin"],"summary":"Admin Guidance Delete","operationId":"admin_guidance_delete_admin_research_guidance__document_id__delete_post","parameters":[{"name":"document_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Document Id"}},{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/billing/refund":{"post":{"tags":["admin"],"summary":"Admin Billing Refund","description":"Refund the charge backing a Stripe invoice.\n\nAdmin UI is deferred to v2; the API endpoint is sufficient for v1.\nRefunds are tagged with `metadata.product = 'lune'` so they are\ndistinguishable from other Stripe products on a shared account\n(consistent with the L-task isolation pattern).","operationId":"admin_billing_refund_admin_billing_refund_post","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminRefundIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminRefundOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/agent-tools":{"get":{"tags":["admin"],"summary":"Agent Tools Page","description":"Test-bed dashboard for the 13 MCP-exposed agent tools.","operationId":"agent_tools_page_admin_agent_tools_get","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/agent-tools/run":{"post":{"tags":["admin"],"summary":"Agent Tools Run","description":"Execute a single MCP tool against the live API stack.\n\nReturns the live JSON response plus the MCP JSON-RPC envelope and the\nequivalent `lune ...` CLI command so the operator can copy them into a\nbug report or demo script.","operationId":"agent_tools_run_admin_agent_tools_run_post","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}},{"name":"lune_admin","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lune Admin"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentToolRunIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Agent Tools Run Admin Agent Tools Run Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/":{"get":{"summary":"Root","operationId":"root__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Root  Get"}}}}}}},"/health":{"get":{"summary":"Health Check","operationId":"health_check_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Health Check Health Get"}}}}}}}},"components":{"schemas":{"AcceptInvitationOut":{"properties":{"org_slug":{"type":"string","title":"Org Slug"},"role":{"type":"string","title":"Role"}},"type":"object","required":["org_slug","role"],"title":"AcceptInvitationOut"},"AdminRefundIn":{"properties":{"invoice_id":{"type":"string","title":"Invoice Id"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},"additionalProperties":false,"type":"object","required":["invoice_id"],"title":"AdminRefundIn"},"AdminRefundOut":{"properties":{"refund_id":{"type":"string","title":"Refund Id"},"amount":{"type":"integer","title":"Amount"},"status":{"type":"string","title":"Status"}},"type":"object","required":["refund_id","amount","status"],"title":"AdminRefundOut"},"AgentToolRunIn":{"properties":{"tool":{"type":"string","title":"Tool"},"inputs":{"additionalProperties":true,"type":"object","title":"Inputs","default":{}}},"additionalProperties":false,"type":"object","required":["tool"],"title":"AgentToolRunIn"},"Body_admin_login_admin_login_post":{"properties":{"key":{"type":"string","title":"Key"},"next":{"type":"string","title":"Next","default":"/admin/dashboard"}},"type":"object","required":["key"],"title":"Body_admin_login_admin_login_post"},"Body_revoke_oauth_revoke_post":{"properties":{"token":{"type":"string","title":"Token"}},"type":"object","required":["token"],"title":"Body_revoke_oauth_revoke_post"},"Body_token_oauth_token_post":{"properties":{"grant_type":{"type":"string","title":"Grant Type"},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"},"code_verifier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code Verifier"},"redirect_uri":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Redirect Uri"},"client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id"},"refresh_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refresh Token"},"resource":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resource"}},"type":"object","required":["grant_type"],"title":"Body_token_oauth_token_post"},"ChangeRoleIn":{"properties":{"role":{"type":"string","pattern":"^(member|admin)$","title":"Role"}},"additionalProperties":false,"type":"object","required":["role"],"title":"ChangeRoleIn"},"ChangeTierIn":{"properties":{"org_slug":{"type":"string","title":"Org Slug"},"new_tier":{"type":"string","enum":["free","pro","max"],"title":"New Tier"}},"additionalProperties":false,"type":"object","required":["org_slug","new_tier"],"title":"ChangeTierIn"},"CheckoutIn":{"properties":{"org_slug":{"type":"string","title":"Org Slug"},"tier":{"type":"string","pattern":"^(pro|max)$","title":"Tier"},"coupon_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Coupon Id"}},"additionalProperties":false,"type":"object","required":["org_slug","tier"],"title":"CheckoutIn"},"CheckoutOut":{"properties":{"checkout_url":{"type":"string","title":"Checkout Url"}},"type":"object","required":["checkout_url"],"title":"CheckoutOut"},"CheckoutSyncOut":{"properties":{"mode":{"type":"string","title":"Mode"},"status":{"type":"string","title":"Status"},"applied":{"type":"boolean","title":"Applied"},"tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tier"},"credits_added":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Credits Added"}},"type":"object","required":["mode","status","applied"],"title":"CheckoutSyncOut"},"CitationsResponse":{"properties":{"paper_id":{"type":"string","title":"Paper Id"},"direction":{"type":"string","enum":["cited_by","cites"],"title":"Direction"},"papers":{"items":{"$ref":"#/components/schemas/CitedPaper"},"type":"array","title":"Papers"}},"type":"object","required":["paper_id","direction","papers"],"title":"CitationsResponse"},"CitedPaper":{"properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"title":{"type":"string","title":"Title"},"authors":{"items":{"type":"string"},"type":"array","title":"Authors","default":[]},"year":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Year"},"doi":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Doi"},"venue":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Venue"},"citation_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Citation Count"}},"type":"object","required":["title"],"title":"CitedPaper"},"Conference":{"properties":{"short_name":{"type":"string","title":"Short Name"},"full_name":{"type":"string","title":"Full Name"},"description":{"type":"string","title":"Description","default":""},"website_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website Url"},"source_config":{"additionalProperties":true,"type":"object","title":"Source Config"},"is_enabled":{"type":"boolean","title":"Is Enabled","default":true},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"},"id":{"type":"string","format":"uuid","title":"Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"paper_count":{"type":"integer","title":"Paper Count","default":0},"last_paper_added_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Paper Added At"},"years":{"items":{"type":"integer"},"type":"array","title":"Years"}},"type":"object","required":["short_name","full_name","id","created_at","updated_at"],"title":"Conference"},"ConferenceExclusion":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"org_id":{"type":"string","format":"uuid","title":"Org Id"},"conference_id":{"type":"string","format":"uuid","title":"Conference Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","org_id","conference_id","created_at"],"title":"ConferenceExclusion","description":"Server-side row for a hidden conference."},"ConferenceExclusionCreate":{"properties":{"conference_id":{"type":"string","title":"Conference Id"}},"additionalProperties":false,"type":"object","required":["conference_id"],"title":"ConferenceExclusionCreate"},"ConsentIn":{"properties":{"client_id":{"type":"string","title":"Client Id"},"redirect_uri":{"type":"string","title":"Redirect Uri"},"scope":{"type":"string","title":"Scope"},"state":{"type":"string","title":"State"},"code_challenge":{"type":"string","title":"Code Challenge"},"code_challenge_method":{"type":"string","title":"Code Challenge Method"},"approved":{"type":"boolean","title":"Approved"},"org_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Org Id"},"resource":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resource"}},"additionalProperties":false,"type":"object","required":["client_id","redirect_uri","scope","state","code_challenge","code_challenge_method","approved"],"title":"ConsentIn"},"CreateInvitationIn":{"properties":{"email":{"type":"string","maxLength":320,"minLength":3,"title":"Email"},"role":{"type":"string","pattern":"^(member|admin)$","title":"Role"}},"additionalProperties":false,"type":"object","required":["email","role"],"title":"CreateInvitationIn"},"CreateKeyIn":{"properties":{"name":{"type":"string","maxLength":64,"minLength":1,"title":"Name"},"scopes":{"items":{"type":"string"},"type":"array","title":"Scopes"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"}},"additionalProperties":false,"type":"object","required":["name"],"title":"CreateKeyIn"},"CreateKeyOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"prefix":{"type":"string","title":"Prefix"},"scopes":{"items":{"type":"string"},"type":"array","title":"Scopes"},"token":{"type":"string","title":"Token"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"}},"type":"object","required":["id","name","prefix","scopes","token","created_at"],"title":"CreateKeyOut"},"CreateOrgIn":{"properties":{"name":{"type":"string","maxLength":128,"minLength":1,"title":"Name"},"slug":{"anyOf":[{"type":"string","maxLength":32,"minLength":3},{"type":"null"}],"title":"Slug"}},"additionalProperties":false,"type":"object","required":["name"],"title":"CreateOrgIn","description":"Team-create payload.\n\n`slug` is optional; when omitted the server derives one from `name`\n(lowercase + hyphenated + uniquified). The dashboard never collects a\nslug from the user - it's an internal identifier, surfacing it as a\nrequired form field is a UX wart we're rid of."},"CreateOrgOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"tier":{"type":"string","title":"Tier"},"is_personal":{"type":"boolean","title":"Is Personal"},"is_onboarded":{"type":"boolean","title":"Is Onboarded"},"role":{"type":"string","title":"Role"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","slug","name","tier","is_personal","is_onboarded","role","created_at"],"title":"CreateOrgOut"},"CreditCheckoutIn":{"properties":{"org_slug":{"type":"string","title":"Org Slug"},"coupon_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Coupon Id"}},"additionalProperties":false,"type":"object","required":["org_slug"],"title":"CreditCheckoutIn"},"DailyInfo":{"properties":{"limit":{"type":"integer","title":"Limit"},"used_today":{"type":"integer","title":"Used Today"},"resets_at":{"type":"string","title":"Resets At"},"credits_remaining":{"type":"integer","title":"Credits Remaining"}},"type":"object","required":["limit","used_today","resets_at","credits_remaining"],"title":"DailyInfo","description":"Per-day quota - single source of truth for current usage."},"DailyUsageRow":{"properties":{"date":{"type":"string","title":"Date"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["date","count"],"title":"DailyUsageRow"},"DcrIn":{"properties":{"client_name":{"type":"string","title":"Client Name","default":"Lune OAuth Client"},"redirect_uris":{"items":{"type":"string"},"type":"array","title":"Redirect Uris"},"grant_types":{"items":{"type":"string"},"type":"array","title":"Grant Types","default":["authorization_code","refresh_token"]},"scope":{"type":"string","title":"Scope","default":"papers:read guidance:read subs:rw account:read"}},"additionalProperties":true,"type":"object","required":["redirect_uris"],"title":"DcrIn","description":"RFC 7591 Dynamic Client Registration request.\n\n`extra='allow'` instead of strict because real-world DCR clients\n(Claude Desktop, ChatGPT custom connectors, Anthropic's MCP\ninspector, …) routinely send fields like ``token_endpoint_auth_method``,\n``response_types``, ``client_uri``, ``logo_uri``, ``application_type``,\n``software_id``, ``software_version``, ``contacts``, ``tos_uri``,\n``policy_uri`` - all defined in RFC 7591 §2 but ones we don't need\nto validate. `extra='forbid'` here causes a 422 that breaks the\nCustom Connector flow before we ever reach our auth code. Accept\nthe extras silently; we only persist the fields we explicitly model."},"DeleteAccountOut":{"properties":{"ok":{"type":"boolean","title":"Ok"},"purge_in_days":{"type":"integer","title":"Purge In Days"}},"type":"object","required":["ok","purge_in_days"],"title":"DeleteAccountOut"},"DevCreditsIn":{"properties":{"org_slug":{"type":"string","title":"Org Slug"},"credits_remaining":{"type":"integer","minimum":0.0,"title":"Credits Remaining","description":"New balance."}},"additionalProperties":false,"type":"object","required":["org_slug","credits_remaining"],"title":"DevCreditsIn"},"DevCreditsOut":{"properties":{"org_slug":{"type":"string","title":"Org Slug"},"credits_remaining":{"type":"integer","title":"Credits Remaining"}},"type":"object","required":["org_slug","credits_remaining"],"title":"DevCreditsOut"},"DevDailyIn":{"properties":{"org_slug":{"type":"string","title":"Org Slug"},"used_today":{"type":"integer","minimum":0.0,"title":"Used Today"}},"additionalProperties":false,"type":"object","required":["org_slug","used_today"],"title":"DevDailyIn"},"DevDailyOut":{"properties":{"org_slug":{"type":"string","title":"Org Slug"},"used_today":{"type":"integer","title":"Used Today"}},"type":"object","required":["org_slug","used_today"],"title":"DevDailyOut"},"DevSubscriptionIn":{"properties":{"org_slug":{"type":"string","title":"Org Slug"},"status":{"type":"string","title":"Status","default":"active"},"cancel_at_period_end":{"type":"boolean","title":"Cancel At Period End","default":false},"period_end_days_from_now":{"type":"integer","maximum":365.0,"minimum":-365.0,"title":"Period End Days From Now","default":30},"pending_tier":{"enum":["pro","max",null],"title":"Pending Tier"}},"additionalProperties":false,"type":"object","required":["org_slug"],"title":"DevSubscriptionIn"},"DevSubscriptionOut":{"properties":{"org_slug":{"type":"string","title":"Org Slug"},"status":{"type":"string","title":"Status"},"cancel_at_period_end":{"type":"boolean","title":"Cancel At Period End"},"current_period_end":{"type":"string","title":"Current Period End"},"pending_tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pending Tier"}},"type":"object","required":["org_slug","status","cancel_at_period_end","current_period_end","pending_tier"],"title":"DevSubscriptionOut"},"DevTierIn":{"properties":{"org_slug":{"type":"string","title":"Org Slug"},"tier":{"type":"string","enum":["free","pro","max"],"title":"Tier"}},"additionalProperties":false,"type":"object","required":["org_slug","tier"],"title":"DevTierIn"},"DevTierOut":{"properties":{"org_slug":{"type":"string","title":"Org Slug"},"tier":{"type":"string","title":"Tier"},"included_units":{"type":"integer","title":"Included Units"}},"type":"object","required":["org_slug","tier","included_units"],"title":"DevTierOut"},"DrainPaper":{"properties":{"id":{"type":"string","title":"Id"},"title":{"type":"string","title":"Title"},"authors":{"items":{"type":"string"},"type":"array","title":"Authors","default":[]},"year":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Year"},"doi":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Doi"},"arxiv_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Arxiv Id"},"abstract":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Abstract"},"pdf_cdn_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pdf Cdn Url"},"citation_count":{"type":"integer","title":"Citation Count","default":0},"occurred_at":{"type":"string","title":"Occurred At"}},"type":"object","required":["id","title","occurred_at"],"title":"DrainPaper"},"DrainResponse":{"properties":{"subscription_id":{"type":"string","title":"Subscription Id"},"papers":{"items":{"$ref":"#/components/schemas/DrainPaper"},"type":"array","title":"Papers"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"},"has_more":{"type":"boolean","title":"Has More"}},"type":"object","required":["subscription_id","papers","has_more"],"title":"DrainResponse"},"FullTextResponse":{"properties":{"paper_id":{"type":"string","title":"Paper Id"},"title":{"type":"string","title":"Title"},"format":{"type":"string","enum":["markdown","json"],"title":"Format"},"body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body"},"sections":{"anyOf":[{"items":{"$ref":"#/components/schemas/FullTextSection"},"type":"array"},{"type":"null"}],"title":"Sections"}},"type":"object","required":["paper_id","title","format"],"title":"FullTextResponse"},"FullTextSection":{"properties":{"heading":{"type":"string","title":"Heading"},"text":{"type":"string","title":"Text"}},"type":"object","required":["heading","text"],"title":"FullTextSection"},"GuidanceSearchHit":{"properties":{"chunk_id":{"type":"string","title":"Chunk Id"},"doc_id":{"type":"string","title":"Doc Id"},"doc_title":{"type":"string","title":"Doc Title"},"doc_source_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Doc Source Url"},"section_name":{"type":"string","title":"Section Name"},"content":{"type":"string","title":"Content"},"score":{"type":"number","title":"Score"}},"type":"object","required":["chunk_id","doc_id","doc_title","section_name","content","score"],"title":"GuidanceSearchHit"},"GuidanceSearchRequest":{"properties":{"query":{"type":"string","maxLength":500,"minLength":1,"title":"Query"},"limit":{"type":"integer","maximum":25.0,"minimum":1.0,"title":"Limit","default":5}},"additionalProperties":false,"type":"object","required":["query"],"title":"GuidanceSearchRequest"},"GuidanceSearchResponse":{"properties":{"query":{"type":"string","title":"Query"},"results":{"items":{"$ref":"#/components/schemas/GuidanceSearchHit"},"type":"array","title":"Results"}},"type":"object","required":["query","results"],"title":"GuidanceSearchResponse"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"InvitationListItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"email":{"type":"string","title":"Email"},"role":{"type":"string","title":"Role"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","email","role","expires_at","created_at"],"title":"InvitationListItem"},"InvitationOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"email":{"type":"string","title":"Email"},"role":{"type":"string","title":"Role"},"token":{"type":"string","title":"Token"},"claim_url":{"type":"string","title":"Claim Url"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","email","role","token","claim_url","expires_at","created_at"],"title":"InvitationOut"},"InvitationPeek":{"properties":{"org_slug":{"type":"string","title":"Org Slug"},"org_name":{"type":"string","title":"Org Name"},"email":{"type":"string","title":"Email"},"role":{"type":"string","title":"Role"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"}},"type":"object","required":["org_slug","org_name","email","role","expires_at"],"title":"InvitationPeek"},"InviteMemberIn":{"properties":{"email":{"type":"string","title":"Email"},"role":{"type":"string","pattern":"^(member|admin)$","title":"Role"}},"additionalProperties":false,"type":"object","required":["email","role"],"title":"InviteMemberIn"},"KeyOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"prefix":{"type":"string","title":"Prefix"},"scopes":{"items":{"type":"string"},"type":"array","title":"Scopes"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Used At"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"},"revoked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Revoked At"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","prefix","scopes","last_used_at","expires_at","revoked_at","created_at"],"title":"KeyOut"},"MatchedChunk":{"properties":{"section_name":{"type":"string","title":"Section Name"},"text":{"type":"string","title":"Text"},"score":{"type":"number","title":"Score"}},"type":"object","required":["section_name","text","score"],"title":"MatchedChunk"},"McpToolInputSchema":{"properties":{"name":{"type":"string","title":"Name"},"kind":{"type":"string","title":"Kind"},"location":{"type":"string","title":"Location"},"required":{"type":"boolean","title":"Required"},"default":{"title":"Default"},"options":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Options"},"placeholder":{"type":"string","title":"Placeholder","default":""},"help":{"type":"string","title":"Help","default":""}},"type":"object","required":["name","kind","location","required"],"title":"McpToolInputSchema"},"McpToolSchema":{"properties":{"name":{"type":"string","title":"Name"},"scope":{"type":"string","title":"Scope"},"description":{"type":"string","title":"Description"},"method":{"type":"string","title":"Method"},"path_template":{"type":"string","title":"Path Template"},"inputs":{"items":{"$ref":"#/components/schemas/McpToolInputSchema"},"type":"array","title":"Inputs"},"cli_template":{"type":"string","title":"Cli Template","default":""}},"type":"object","required":["name","scope","description","method","path_template","inputs"],"title":"McpToolSchema"},"MemberOut":{"properties":{"user_id":{"type":"string","format":"uuid","title":"User Id"},"email":{"type":"string","title":"Email"},"role":{"type":"string","title":"Role"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["user_id","email","role","created_at"],"title":"MemberOut"},"NotificationListResponse":{"properties":{"notifications":{"items":{"$ref":"#/components/schemas/NotificationResponse"},"type":"array","title":"Notifications"},"total":{"type":"integer","title":"Total"},"unread_count":{"type":"integer","title":"Unread Count"},"page":{"type":"integer","title":"Page"},"limit":{"type":"integer","title":"Limit"},"total_pages":{"type":"integer","title":"Total Pages"}},"type":"object","required":["notifications","total","unread_count","page","limit","total_pages"],"title":"NotificationListResponse"},"NotificationResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"org_id":{"type":"string","format":"uuid","title":"Org Id"},"paper_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Paper Id"},"conference_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Conference Id"},"notification_type":{"type":"string","title":"Notification Type"},"is_read":{"type":"boolean","title":"Is Read"},"emailed":{"type":"boolean","title":"Emailed"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"paper":{"anyOf":[{"$ref":"#/components/schemas/PaperResponse"},{"type":"null"}]}},"type":"object","required":["id","org_id","notification_type","is_read","emailed","created_at"],"title":"NotificationResponse"},"OrgDetail":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"tier":{"type":"string","title":"Tier"},"is_personal":{"type":"boolean","title":"Is Personal"},"is_onboarded":{"type":"boolean","title":"Is Onboarded"},"overage_cap_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Overage Cap Cents"},"stripe_customer_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stripe Customer Id"},"members":{"items":{"$ref":"#/components/schemas/MemberOut"},"type":"array","title":"Members"},"your_role":{"type":"string","title":"Your Role"}},"type":"object","required":["id","slug","name","tier","is_personal","is_onboarded","overage_cap_cents","stripe_customer_id","members","your_role"],"title":"OrgDetail"},"OrgInfo":{"properties":{"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"tier":{"type":"string","title":"Tier"},"subscription":{"anyOf":[{"$ref":"#/components/schemas/SubscriptionInfo"},{"type":"null"}]}},"type":"object","required":["slug","name","tier"],"title":"OrgInfo"},"OrgListItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"tier":{"type":"string","title":"Tier"},"is_personal":{"type":"boolean","title":"Is Personal"},"is_onboarded":{"type":"boolean","title":"Is Onboarded"},"role":{"type":"string","title":"Role"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","slug","name","tier","is_personal","is_onboarded","role","created_at"],"title":"OrgListItem"},"PaperChunkResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"paper_id":{"type":"string","format":"uuid","title":"Paper Id"},"section_name":{"type":"string","title":"Section Name"},"chunk_index":{"type":"integer","title":"Chunk Index"},"text":{"type":"string","title":"Text"},"context_prefix":{"type":"string","title":"Context Prefix"},"token_count":{"type":"integer","title":"Token Count"}},"type":"object","required":["id","paper_id","section_name","chunk_index","text","context_prefix","token_count"],"title":"PaperChunkResponse"},"PaperListResponse":{"properties":{"papers":{"items":{"$ref":"#/components/schemas/PaperResponse"},"type":"array","title":"Papers"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"limit":{"type":"integer","title":"Limit"},"total_pages":{"type":"integer","title":"Total Pages"}},"type":"object","required":["papers","total","page","limit","total_pages"],"title":"PaperListResponse"},"PaperResponse":{"properties":{"external_id":{"type":"string","title":"External Id"},"source":{"type":"string","title":"Source"},"title":{"type":"string","title":"Title"},"abstract":{"type":"string","title":"Abstract","default":""},"authors":{"items":{"type":"string"},"type":"array","title":"Authors"},"year":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Year"},"doi":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Doi"},"arxiv_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Arxiv Id"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"},"pdf_cdn_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pdf Cdn Url"},"ai_tldr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ai Tldr"},"ai_contributions":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Ai Contributions"},"ai_methodology":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ai Methodology"},"keywords":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Keywords"},"citation_count":{"type":"integer","title":"Citation Count","default":0},"processing_status":{"type":"string","title":"Processing Status","default":"pending"},"review_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Review Status"},"id":{"type":"string","format":"uuid","title":"Id"},"conference_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Conference Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"conference":{"anyOf":[{"$ref":"#/components/schemas/Conference"},{"type":"null"}]}},"type":"object","required":["external_id","source","title","id","created_at","updated_at"],"title":"PaperResponse"},"PortalIn":{"properties":{"org_slug":{"type":"string","title":"Org Slug"}},"additionalProperties":false,"type":"object","required":["org_slug"],"title":"PortalIn"},"PortalOut":{"properties":{"portal_url":{"type":"string","title":"Portal Url"}},"type":"object","required":["portal_url"],"title":"PortalOut"},"ResumeIn":{"properties":{"org_slug":{"type":"string","title":"Org Slug"}},"additionalProperties":false,"type":"object","required":["org_slug"],"title":"ResumeIn"},"SearchHit":{"properties":{"paper_id":{"type":"string","format":"uuid","title":"Paper Id"},"title":{"type":"string","title":"Title"},"authors":{"items":{"type":"string"},"type":"array","title":"Authors"},"year":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Year"},"conference":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conference"},"abstract":{"type":"string","title":"Abstract","default":""},"doi":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Doi"},"arxiv_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Arxiv Id"},"pdf_cdn_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pdf Cdn Url"},"citation_count":{"type":"integer","title":"Citation Count","default":0},"score":{"type":"number","title":"Score"},"matched_chunks":{"items":{"$ref":"#/components/schemas/MatchedChunk"},"type":"array","title":"Matched Chunks"}},"type":"object","required":["paper_id","title","score"],"title":"SearchHit","description":"Slim, flat envelope for one search result.\n\nReplaces the previous nested ``{paper: PaperResponse, score, ...}``\nshape on the wire. Drops fields that are either redundant\n(``external_id``, ``source``, ``conference_id`` — already covered by\nthe canonical ``conference`` short_name), internal (``processing_status``,\n``review_status``, ``created_at``, ``updated_at``), or always NULL on\nnew papers post-pivot (``ai_tldr``, ``ai_contributions``,\n``ai_methodology``, ``keywords`` — the legacy EnrichWorker that\npopulated those was deleted). Net result: ~22 fields per hit → ~10,\nsmaller wire payload, faster client serialisation.\n\nAgents that need fields beyond this slim envelope (e.g. the full\nabstract, the AI methodology summary if it ever returns) can call\n``get_paper(id)`` for the full ``PaperResponse``."},"SearchRequest":{"properties":{"query":{"type":"string","maxLength":500,"minLength":1,"title":"Query"},"conference_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conference Id"},"conference_short_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conference Short Name"},"year":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Year"},"limit":{"type":"integer","maximum":50.0,"minimum":1.0,"title":"Limit","default":10},"sort_by":{"type":"string","enum":["relevance","date","citations"],"title":"Sort By","default":"relevance"},"use_hyde":{"type":"boolean","title":"Use Hyde","default":false},"expand_queries":{"type":"boolean","title":"Expand Queries","default":false}},"additionalProperties":false,"type":"object","required":["query"],"title":"SearchRequest"},"SearchResponse":{"properties":{"results":{"items":{"$ref":"#/components/schemas/SearchHit"},"type":"array","title":"Results"},"total":{"type":"integer","title":"Total"},"query":{"type":"string","title":"Query"}},"type":"object","required":["results","total","query"],"title":"SearchResponse"},"Subscription":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"org_id":{"type":"string","format":"uuid","title":"Org Id"},"conference_id":{"type":"string","format":"uuid","title":"Conference Id"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"notify_email":{"type":"boolean","title":"Notify Email"},"notify_in_app":{"type":"boolean","title":"Notify In App"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","org_id","conference_id","notify_email","notify_in_app","created_at"],"title":"Subscription"},"SubscriptionCreate":{"properties":{"conference_id":{"type":"string","title":"Conference Id"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"notify_email":{"type":"boolean","title":"Notify Email","default":true},"notify_in_app":{"type":"boolean","title":"Notify In App","default":true}},"additionalProperties":false,"type":"object","required":["conference_id"],"title":"SubscriptionCreate"},"SubscriptionInfo":{"properties":{"status":{"type":"string","title":"Status"},"cancel_at_period_end":{"type":"boolean","title":"Cancel At Period End"},"current_period_end":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Period End"},"pending_tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pending Tier"},"pending_tier_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pending Tier At"}},"type":"object","required":["status","cancel_at_period_end","current_period_end"],"title":"SubscriptionInfo","description":"Snapshot of the org's Stripe subscription. Surfaced on whoami so the\ndashboard can show pending state changes (e.g. \"Pro · cancels Mar 15\")\nwithout an extra round-trip per page."},"SuggestionItem":{"properties":{"type":{"type":"string","enum":["paper","author","conference"],"title":"Type"},"label":{"type":"string","title":"Label"},"sublabel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sublabel"},"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"}},"type":"object","required":["type","label"],"title":"SuggestionItem"},"SuggestionsResponse":{"properties":{"suggestions":{"items":{"$ref":"#/components/schemas/SuggestionItem"},"type":"array","title":"Suggestions"}},"type":"object","required":["suggestions"],"title":"SuggestionsResponse"},"TestPatIn":{"properties":{"org_slug":{"type":"string","title":"Org Slug"}},"additionalProperties":false,"type":"object","required":["org_slug"],"title":"TestPatIn"},"TestPatOut":{"properties":{"token":{"type":"string","title":"Token"},"expires_at":{"type":"string","title":"Expires At"},"scopes":{"items":{"type":"string"},"type":"array","title":"Scopes"}},"type":"object","required":["token","expires_at","scopes"],"title":"TestPatOut"},"TransferOwnershipIn":{"properties":{"new_owner_user_id":{"type":"string","format":"uuid","title":"New Owner User Id"}},"additionalProperties":false,"type":"object","required":["new_owner_user_id"],"title":"TransferOwnershipIn"},"UpdateOrgIn":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":128,"minLength":1},{"type":"null"}],"title":"Name"},"overage_cap_cents":{"anyOf":[{"type":"integer","maximum":100000.0,"minimum":0.0},{"type":"null"}],"title":"Overage Cap Cents"},"is_onboarded":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Onboarded"}},"additionalProperties":false,"type":"object","title":"UpdateOrgIn"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WhoAmIOut":{"properties":{"org":{"$ref":"#/components/schemas/OrgInfo"},"daily":{"$ref":"#/components/schemas/DailyInfo"},"scopes":{"items":{"type":"string"},"type":"array","title":"Scopes"},"auth_method":{"type":"string","title":"Auth Method"}},"type":"object","required":["org","daily","scopes","auth_method"],"title":"WhoAmIOut"}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"}}}}