{"openapi":"3.1.0","info":{"title":"AtlasRepo Public API","version":"2026-09-08","description":"Platform API serves AtlasRepo accounts, access, billing and approved public catalog and content projections."},"servers":[{"url":"https://public-api.atlasrepo.com","description":"AtlasRepo public API"}],"security":[{"ApiKeyAuth":[]},{"BearerAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key"},"BearerAuth":{"type":"http","scheme":"bearer"},"AccountSessionCookie":{"type":"apiKey","in":"cookie","name":"rse_session","description":"Native HttpOnly account session. Global RAG, personal solutions and n8n actions additionally require an exact trusted Origin; writes require application/json."}},"schemas":{"CourseOutline":{"type":"object","required":["id","slug","releaseId","releaseNo","title","summary","locale","author","chapters"],"properties":{"id":{"type":"string"},"slug":{"type":"string","pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"},"releaseId":{"type":"string"},"releaseNo":{"type":"integer","minimum":1},"publishedAt":{"type":"string","format":"date-time"},"title":{"type":"string"},"summary":{"type":"string"},"locale":{"type":"string"},"author":{"type":"object","additionalProperties":true},"chapters":{"type":"array","items":{"type":"object","required":["id","title","materials"],"properties":{"id":{"type":"string"},"title":{"type":"string"},"materials":{"type":"array","items":{"$ref":"#/components/schemas/CourseMaterialOutline"}}}}}}},"CourseMaterialOutline":{"type":"object","additionalProperties":false,"required":["id","title","type","locked","lockReason"],"properties":{"id":{"type":"string"},"title":{"type":"string"},"type":{"type":"string","enum":["article","instruction","file","video","task"]},"durationSeconds":{"type":["integer","null"],"minimum":0},"locked":{"type":"boolean"},"lockReason":{"type":["string","null"]}}},"CourseOutlineV2":{"type":"object","additionalProperties":true,"required":["id","slug","releaseId","releaseNo","schemaVersion","requestedLocale","resolvedLocale","localeFallback","title","summary","chapters","counts"],"properties":{"id":{"type":"string"},"slug":{"type":"string"},"releaseId":{"type":"string"},"releaseNo":{"type":"integer"},"schemaVersion":{"type":"integer","enum":[2,3]},"requestedLocale":{"type":"string"},"resolvedLocale":{"type":"string"},"localeFallback":{"type":"boolean"},"title":{"type":"string"},"summary":{"type":"string"},"coverAssetId":{"type":["string","null"]},"counts":{"type":"object","additionalProperties":false,"required":["lessonCount","promptCount","skillCount"],"properties":{"lessonCount":{"type":"integer"},"promptCount":{"type":"integer"},"skillCount":{"type":"integer"}}},"chapters":{"type":"array","items":{"type":"object"}}}},"PulseResponse":{"type":"object","additionalProperties":false,"required":["generated_at","data_freshness","score_version","next_cursor","totals","partial","view","sections"],"properties":{"generated_at":{"type":"string","format":"date-time"},"data_freshness":{"type":"object","additionalProperties":false,"required":["status","newest_at","stale_after_seconds"],"properties":{"status":{"type":"string","enum":["fresh","stale","partial","empty"]},"newest_at":{"type":["string","null"],"format":"date-time"},"stale_after_seconds":{"type":"integer","minimum":1}}},"score_version":{"type":"string","const":"pulse-read-model-v2"},"next_cursor":{"type":"null"},"totals":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"partial":{"type":"boolean"},"view":{"type":"string","enum":["home","full"]},"sections":{"type":"object","additionalProperties":false,"properties":{"repositories":{"$ref":"#/components/schemas/PulseSection"},"news":{"$ref":"#/components/schemas/PulseSection"},"workflows":{"$ref":"#/components/schemas/PulseSection"},"templates":{"$ref":"#/components/schemas/PulseSection"},"skills":{"$ref":"#/components/schemas/PulseSection"},"mcp":{"$ref":"#/components/schemas/PulseSection"},"models":{"$ref":"#/components/schemas/PulseSection"},"ai_companies":{"$ref":"#/components/schemas/PulseSection"}}}}},"PulseSection":{"type":"object","additionalProperties":false,"required":["state","source","reason","last_updated_at","total","page_size","next_cursor","watermark","items"],"properties":{"state":{"type":"string","enum":["ready","empty","unavailable"]},"source":{"type":"string"},"reason":{"type":["string","null"],"enum":["no_published_items","no_published_model_catalog","source_unavailable",null]},"last_updated_at":{"type":["string","null"],"format":"date-time"},"total":{"type":"integer","minimum":0},"page_size":{"type":"integer","minimum":0},"next_cursor":{"type":["string","null"]},"watermark":{"type":["string","null"],"format":"date-time"},"items":{"type":"array","items":{"$ref":"#/components/schemas/PulseItem"}}}},"PulseItem":{"type":"object","additionalProperties":false,"required":["id","kind","title","summary","href","source_url","image_url","score","tags","updated_at"],"properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["repositories","news","workflows","templates","skills","mcp","models","ai_companies"]},"title":{"type":"string"},"summary":{"type":"string"},"href":{"type":"string"},"source_url":{"type":"string"},"image_url":{"type":["string","null"]},"score":{"type":["number","null"]},"tags":{"type":"array","items":{"type":"string"}},"updated_at":{"type":["string","null"],"format":"date-time"}}},"Category":{"type":"object","required":["name","description","activeRepoCount"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"activeRepoCount":{"type":"integer","minimum":0}}},"McpOAuthConnection":{"type":"object","additionalProperties":false,"required":["id","clientId","clientName","preview","scope","status","createdAt","lastUsedAt","expiresAt","revokedAt","revokedReason"],"properties":{"id":{"type":"string"},"clientId":{"type":"string"},"clientName":{"type":"string"},"preview":{"type":"string","description":"Non-secret token preview"},"scope":{"type":"string"},"status":{"type":"string","enum":["active","expired","revoked"]},"createdAt":{"type":["string","null"],"format":"date-time"},"lastUsedAt":{"type":["string","null"],"format":"date-time"},"expiresAt":{"type":["string","null"],"format":"date-time"},"revokedAt":{"type":["string","null"],"format":"date-time"},"revokedReason":{"type":["string","null"]}}},"RequestQuota":{"type":"object","additionalProperties":false,"required":["tier","plan","unit","limit","used","remaining","windowSeconds","resetAt","unlimited"],"properties":{"tier":{"type":"string"},"plan":{"type":"string"},"unit":{"type":"string","const":"requests"},"limit":{"type":["integer","null"],"minimum":0},"used":{"type":"integer","minimum":0},"remaining":{"type":["integer","null"],"minimum":0},"windowSeconds":{"type":"integer","minimum":1,"description":"Length of the current request-quota window; not necessarily a monthly allowance."},"resetAt":{"type":["string","null"],"format":"date-time"},"unlimited":{"type":"boolean"}}}}},"tags":[{"name":"Solutions"},{"name":"Course Learning"},{"name":"Attribution","description":"Public allowlisted content campaign redirects"},{"name":"Core","description":"Authenticated AtlasRepo Core workspaces and evidence-backed task dossiers"},{"name":"Courses","description":"Native immutable Course publishing and ACL-aware learner flow"},{"name":"Pulse","description":"Public fail-soft projections for AtlasRepo home and Pulse surfaces"},{"name":"Content","description":"Published editorial content and internal Scout publication projection"},{"name":"Catalog","description":"Ranked open-source repository catalog"},{"name":"Stories","description":"Published use-case stories and workflows"},{"name":"Tools","description":"Normalized tools referenced by stories"},{"name":"Skills","description":"Published AI-agent skills with source, license, compatibility and risk metadata"},{"name":"AI Companies"},{"name":"Models"},{"name":"Account","description":"Authenticated account and API key management"}],"paths":{"/api/assistant/solutions/search":{"post":{"tags":["Solutions"],"summary":"Find up to three current public source-evidence candidates for a private task","security":[{"BearerAuth":[]},{"AccountSessionCookie":[]}],"description":"Opt-in evidence_search mode, not model generation or verified compatibility. No task is persisted and no action is executed. Stale, changed and withdrawn reviews are excluded. 16 KiB body cap.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["task","constraints","environment","direction","locale"],"properties":{"task":{"type":"string","minLength":12,"maxLength":1200},"constraints":{"type":"string","maxLength":1200},"environment":{"type":"string","maxLength":400},"direction":{"enum":["auto","coding-agents","work-automation"]},"locale":{"enum":["ru","en","zh"]}}}}}},"responses":{"200":{"description":"atlas-solution-selection.v1; candidates or insufficient_evidence, explicit missing checks and source citations."},"401":{"description":"A current native account session is required; course agent keys are not accepted."},"403":{"description":"Cookie requests require an exact trusted Origin, including private reads."},"404":{"description":"Disabled new search/save feature or missing owned dossier."},"409":{"description":"Evidence, idempotency request, version or personal workspace changed."},"415":{"description":"Cookie-authenticated writes require application/json."},"422":{"description":"Closed bounded input is invalid, contains credentials or lacks explicit confirmation."},"429":{"description":"Request or 100-active-personal-dossier limit reached."},"503":{"description":"Unavailable, with private input/diagnostics omitted."}}}},"/api/assistant/solutions/save":{"post":{"tags":["Solutions"],"summary":"Save the explicitly chosen evidence as a private Core Task Dossier v0.2","security":[{"BearerAuth":[]},{"AccountSessionCookie":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,160}$"}}],"description":"Rechecks source version, current public review digest, native session and an owner-only Core workspace. Idempotent; does not execute or mark a result complete.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["query","items","confirm"],"properties":{"query":{"type":"object","additionalProperties":false,"required":["task","constraints","environment","direction","locale"],"properties":{"task":{"type":"string","minLength":12,"maxLength":1200},"constraints":{"type":"string","maxLength":1200},"environment":{"type":"string","maxLength":400},"direction":{"enum":["auto","coding-agents","work-automation"]},"locale":{"enum":["ru","en","zh"]}}},"confirm":{"const":true},"items":{"type":"array","minItems":1,"maxItems":3,"items":{"type":"object","additionalProperties":false,"required":["materialId","sourceVersion","reviewDigest"],"properties":{"materialId":{"type":"string","pattern":"^repo:[a-z0-9_.-]{1,100}/[a-z0-9_.-]{1,100}$"},"sourceVersion":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"reviewDigest":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"}}}}}}}}},"responses":{"200":{"description":"Owned dossier metadata or exact replay, applicationCompleted=false."},"401":{"description":"A current native account session is required; course agent keys are not accepted."},"403":{"description":"Cookie requests require an exact trusted Origin, including private reads."},"404":{"description":"Disabled new search/save feature or missing owned dossier."},"409":{"description":"Evidence, idempotency request, version or personal workspace changed."},"415":{"description":"Cookie-authenticated writes require application/json."},"422":{"description":"Closed bounded input is invalid, contains credentials or lacks explicit confirmation."},"429":{"description":"Request or 100-active-personal-dossier limit reached."},"503":{"description":"Unavailable, with private input/diagnostics omitted."}}}},"/api/assistant/solutions/dossiers":{"get":{"tags":["Solutions"],"summary":"Read at most 100 active personal dossier metadata entries","security":[{"BearerAuth":[]},{"AccountSessionCookie":[]}],"description":"Available to the owner even when new search/save is disabled. Does not create a workspace.","responses":{"200":{"description":"atlas-solution-dossiers.v1 metadata only."},"401":{"description":"A current native account session is required; course agent keys are not accepted."},"403":{"description":"Cookie requests require an exact trusted Origin, including private reads."},"404":{"description":"Disabled new search/save feature or missing owned dossier."},"409":{"description":"Evidence, idempotency request, version or personal workspace changed."},"415":{"description":"Cookie-authenticated writes require application/json."},"422":{"description":"Closed bounded input is invalid, contains credentials or lacks explicit confirmation."},"429":{"description":"Request or 100-active-personal-dossier limit reached."},"503":{"description":"Unavailable, with private input/diagnostics omitted."}}}},"/api/assistant/solutions/dossiers/{id}":{"get":{"tags":["Solutions"],"summary":"Read one owned historical decision dossier","security":[{"BearerAuth":[]},{"AccountSessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"description":"Private, no-store. Saved evidence is historical, not a current recommendation; re-run search before applying it.","responses":{"200":{"description":"atlas-solution-dossier.v1 with a private Core document."},"401":{"description":"A current native account session is required; course agent keys are not accepted."},"403":{"description":"Cookie requests require an exact trusted Origin, including private reads."},"404":{"description":"Disabled new search/save feature or missing owned dossier."},"409":{"description":"Evidence, idempotency request, version or personal workspace changed."},"415":{"description":"Cookie-authenticated writes require application/json."},"422":{"description":"Closed bounded input is invalid, contains credentials or lacks explicit confirmation."},"429":{"description":"Request or 100-active-personal-dossier limit reached."},"503":{"description":"Unavailable, with private input/diagnostics omitted."}}}},"/api/assistant/solutions/dossiers/{id}/archive":{"post":{"tags":["Solutions"],"summary":"Archive one personal dossier with version and explicit confirmation","security":[{"BearerAuth":[]},{"AccountSessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,160}$"}}],"description":"Retains immutable Core revision history. Archiving is not permanent erasure and remains available when search/save is disabled.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["version","confirm"],"properties":{"version":{"type":"integer","minimum":1},"confirm":{"const":true}}}}}},"responses":{"200":{"description":"Archived metadata or exact replay; a changed request/version conflicts."},"401":{"description":"A current native account session is required; course agent keys are not accepted."},"403":{"description":"Cookie requests require an exact trusted Origin, including private reads."},"404":{"description":"Disabled new search/save feature or missing owned dossier."},"409":{"description":"Evidence, idempotency request, version or personal workspace changed."},"415":{"description":"Cookie-authenticated writes require application/json."},"422":{"description":"Closed bounded input is invalid, contains credentials or lacks explicit confirmation."},"429":{"description":"Request or 100-active-personal-dossier limit reached."},"503":{"description":"Unavailable, with private input/diagnostics omitted."}}}},"/api/solutions/collections":{"get":{"tags":["Solutions"],"summary":"Read two evidence-backed selections, up to five solutions each","security":[],"description":"Requires solution discovery and review flags. Source overviews are not runtime checks. No authentication required.","responses":{"200":{"description":"atlas-solution-collections.v1 public allowlist; no private findings or inferred quality score."},"400":{"description":"Invalid comparison identities."},"404":{"description":"Feature disabled or unknown collection."},"429":{"description":"Rate limited."},"503":{"description":"Evidence temporarily unavailable. Not an empty successful collection."}}}},"/api/solutions/collections/{slug}":{"get":{"tags":["Solutions"],"summary":"Read one evidence-backed selection","security":[],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","enum":["coding-agents","work-automation"]}}],"responses":{"200":{"description":"atlas-solution-collections.v1 public allowlist; no private findings or inferred quality score."},"400":{"description":"Invalid comparison identities."},"404":{"description":"Feature disabled or unknown collection."},"429":{"description":"Rate limited."},"503":{"description":"Evidence temporarily unavailable. Not an empty successful collection."}}}},"/api/solutions/compare":{"get":{"tags":["Solutions"],"summary":"Compare one to three available public solution reviews","security":[],"description":"Withdrawn, quarantined or missing sources are returned as unavailable, never replaced by another result.","parameters":[{"name":"material","in":"query","required":true,"style":"form","explode":true,"schema":{"type":"array","minItems":1,"maxItems":3,"uniqueItems":true,"items":{"type":"string","pattern":"^repo:[a-zA-Z0-9_.-]{1,100}/[a-zA-Z0-9_.-]{1,100}$"}}}],"responses":{"200":{"description":"atlas-solution-collections.v1 public allowlist; no private findings or inferred quality score."},"400":{"description":"Invalid comparison identities."},"404":{"description":"Feature disabled or unknown collection."},"429":{"description":"Rate limited."},"503":{"description":"Evidence temporarily unavailable. Not an empty successful collection."}}}},"/api/actions/n8n/templates/{templateId}":{"get":{"tags":["Solutions"],"summary":"Preview an approved inactive n8n export and its exact confirmation scope","security":[{"BearerAuth":[]},{"AccountSessionCookie":[]}],"parameters":[{"name":"templateId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Version-bound export projection. Prepared/downloaded is never a successful import or runtime result."},"401":{"description":"Current native account session required; service keys and anonymous access are not accepted."},"403":{"description":"Cookie requests require an exact trusted Origin, including private reads and downloads."},"404":{"description":"Disabled, unavailable, revoked, archived or not owned."},"409":{"description":"Version, confirmation, workspace, result or idempotency conflict. Obtain a fresh preview; do not retry a changed scope automatically."},"415":{"description":"Cookie-authenticated writes require application/json."},"429":{"description":"Per-account rate limit or 100 active personal Core dossiers exceeded."},"503":{"description":"Source delivery, integrity verification or persistence unavailable."}},"description":"N8N_EXPORT_ENABLED required. Independent of the disabled generic Core artifact API. No file transfer, installation or execution on preview. Includes the pinned Core release, source/hash, license, attribution, expiry and zero-cost download permissions."}},"/api/actions/n8n/templates/{templateId}/confirm":{"post":{"tags":["Solutions"],"summary":"Confirm one exact export and retain its prepared result in the owner's personal Core workspace","security":[{"BearerAuth":[]},{"AccountSessionCookie":[]}],"parameters":[{"name":"templateId","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,160}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["contract","confirm","recipeDigest","sourceVersion","target","permissionsDigest","maximumCostCents"],"properties":{"contract":{"const":"atlas-n8n-export-confirmation.v1"},"confirm":{"const":true},"recipeDigest":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"sourceVersion":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"permissionsDigest":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"maximumCostCents":{"const":0},"target":{"type":"object","additionalProperties":false,"required":["kind","ownership","adapterId"],"properties":{"kind":{"const":"client_n8n"},"ownership":{"const":"customer"},"adapterId":{"type":"null"}}}}}}}},"responses":{"200":{"description":"Version-bound export projection. Prepared/downloaded is never a successful import or runtime result."},"400":{"description":"Idempotency key required."},"401":{"description":"Current native account session required; service keys and anonymous access are not accepted."},"403":{"description":"Cookie requests require an exact trusted Origin, including private reads and downloads."},"404":{"description":"Disabled, unavailable, revoked, archived or not owned."},"409":{"description":"Version, confirmation, workspace, result or idempotency conflict. Obtain a fresh preview; do not retry a changed scope automatically."},"413":{"description":"Body exceeds 4 KiB."},"415":{"description":"Cookie-authenticated writes require application/json."},"422":{"description":"Explicit confirmation required."},"429":{"description":"Per-account rate limit or 100 active personal Core dossiers exceeded."},"503":{"description":"Source delivery, integrity verification or persistence unavailable."}}}},"/api/actions/n8n/results":{"get":{"tags":["Solutions"],"summary":"Read up to 100 own active export result records, even when new exports are disabled","security":[{"BearerAuth":[]},{"AccountSessionCookie":[]}],"responses":{"200":{"description":"Version-bound export projection. Prepared/downloaded is never a successful import or runtime result."},"401":{"description":"Current native account session required; service keys and anonymous access are not accepted."},"403":{"description":"Cookie requests require an exact trusted Origin, including private reads and downloads."},"404":{"description":"Disabled, unavailable, revoked, archived or not owned."},"409":{"description":"Version, confirmation, workspace, result or idempotency conflict. Obtain a fresh preview; do not retry a changed scope automatically."},"415":{"description":"Cookie-authenticated writes require application/json."},"429":{"description":"Per-account rate limit or 100 active personal Core dossiers exceeded."},"503":{"description":"Source delivery, integrity verification or persistence unavailable."}}}},"/api/actions/n8n/results/{dossierId}":{"get":{"tags":["Solutions"],"summary":"Read one unchanged owned export result","security":[{"BearerAuth":[]},{"AccountSessionCookie":[]}],"parameters":[{"name":"dossierId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Version-bound export projection. Prepared/downloaded is never a successful import or runtime result."},"401":{"description":"Current native account session required; service keys and anonymous access are not accepted."},"403":{"description":"Cookie requests require an exact trusted Origin, including private reads and downloads."},"404":{"description":"Disabled, unavailable, revoked, archived or not owned."},"409":{"description":"Version, confirmation, workspace, result or idempotency conflict. Obtain a fresh preview; do not retry a changed scope automatically."},"415":{"description":"Cookie-authenticated writes require application/json."},"429":{"description":"Per-account rate limit or 100 active personal Core dossiers exceeded."},"503":{"description":"Source delivery, integrity verification or persistence unavailable."}}}},"/api/actions/n8n/results/{dossierId}/file":{"get":{"tags":["Solutions"],"summary":"Download the exact ZIP after rechecking current approval and account access","security":[{"BearerAuth":[]},{"AccountSessionCookie":[]}],"parameters":[{"name":"dossierId","in":"path","required":true,"schema":{"type":"string"}},{"name":"If-Match","in":"header","required":true,"schema":{"type":"string"},"description":"Quoted bundle.digest from the confirmed result."}],"description":"No public/signed download URL. Rechecks Scout expiry, revocation and current version on every read. The ZIP contains workflow.json, ATTRIBUTION.txt, manifest.json and README.txt. JSON is inactive and unchanged from review. No import or activation occurs.","responses":{"200":{"description":"Private no-store attachment, exact reviewed JSON and attribution.","content":{"application/zip":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Current native account session required; service keys and anonymous access are not accepted."},"403":{"description":"Cookie requests require an exact trusted Origin, including private reads and downloads."},"404":{"description":"Disabled, unavailable, revoked, archived or not owned."},"409":{"description":"Version, confirmation, workspace, result or idempotency conflict. Obtain a fresh preview; do not retry a changed scope automatically."},"415":{"description":"Cookie-authenticated writes require application/json."},"428":{"description":"Exact bundle digest required."},"429":{"description":"Per-account rate limit or 100 active personal Core dossiers exceeded."},"503":{"description":"Source delivery, integrity verification or persistence unavailable."}}}},"/api/assistant/knowledge/conversations":{"get":{"tags":["Solutions"],"summary":"List the account owner's private Atlas AI conversations","security":[{"BearerAuth":[]},{"AccountSessionCookie":[]}],"responses":{"200":{"description":"atlas-ai-conversations.v1; at most 100 active conversations, title and UTC timestamps only."},"401":{"description":"Current native account session required."}}},"post":{"tags":["Solutions"],"summary":"Create a private Atlas AI conversation with an idempotent client UUID","security":[{"BearerAuth":[]},{"AccountSessionCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["id","title"],"properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string","minLength":1,"maxLength":120}}}}}},"responses":{"201":{"description":"atlas-ai-conversation.v1 metadata; no inference performed."},"409":{"description":"Conflicting conversation ID."},"429":{"description":"Conversation capacity reached."}}}},"/api/assistant/knowledge/conversations/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"tags":["Solutions"],"summary":"Read owner-only messages with current source access rechecks","security":[{"BearerAuth":[]},{"AccountSessionCookie":[]}],"parameters":[{"name":"before","in":"query","schema":{"type":"integer","minimum":1,"maximum":101,"default":101}}],"responses":{"200":{"description":"atlas-ai-conversation.v1; at most 20 turns, nextBefore cursor. Changed/unavailable source context withholds saved answer and citations."},"404":{"description":"Missing, archived or owned by another account."}}},"delete":{"tags":["Solutions"],"summary":"Archive an owner-only conversation without permanent erasure","security":[{"BearerAuth":[]},{"AccountSessionCookie":[]}],"responses":{"200":{"description":"archived=true, permanentlyDeleted=false."},"404":{"description":"Missing, archived or owned by another account."}}}},"/api/templates/{slug}":{"get":{"tags":["Solutions"],"summary":"Read the published public description behind a template citation","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"atlas-public-template.v1. Public description and source link only; no workflow bytes, credentials or runtime claims."},"404":{"description":"Not published, not public, invalid slug or feature disabled."},"503":{"description":"Source unavailable."}}}},"/api/assistant/knowledge/query":{"post":{"tags":["Solutions"],"summary":"Ask Atlas AI using current published and authorized AtlasRepo material","security":[{"BearerAuth":[]},{"AccountSessionCookie":[]}],"description":"Federated full-text RAG with native publication/course ACL checks before generation and response. Optional conversationId and requestId must be supplied together for owner-only durable history; otherwise ephemeral. Completed identical requests replay after current source checks, without inference. No learner history is indexed, no prior messages are automatically sent to a provider, and no application action is performed. Requires ATLAS_AI_ENABLED; external generation separately requires ATLAS_AI_EXTERNAL_CONTENT_ENABLED. Eight requests per minute; 16 KiB body limit.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["question"],"dependentRequired":{"conversationId":["requestId"],"requestId":["conversationId"]},"properties":{"question":{"type":"string","minLength":3,"maxLength":4000},"conversationId":{"type":"string","format":"uuid"},"requestId":{"type":"string","format":"uuid"}}}}}},"responses":{"200":{"description":"atlas-knowledge-answer.v1. mode=rag has a relevance-screened generated answer, exact citations and missing checks; an abstention has no citations. mode=retrieval returns excerpts without invented prose and includes fallbackReason. Source coverage distinguishes searched from unavailable. persisted=true only after durable storage succeeds, with matching conversationId/requestId; otherwise persisted=false. replayed=true indicates a revalidated saved turn without new inference. executionAuthorized=false always. Source provenance is not runtime verification."},"401":{"description":"Current native account session required. Bearer and existing HttpOnly session cookies are supported. Scoped course credentials do not authorize global search."},"403":{"description":"Cookie-only requests require an exact trusted Origin; absent or wildcard origins are denied."},"404":{"description":"Feature disabled."},"405":{"description":"POST required."},"409":{"description":"One or more context sources, permissions or session changed; no answer or citations returned."},"413":{"description":"Body too large."},"415":{"description":"JSON content type required before retrieval or generation."},"422":{"description":"Invalid input or credentials detected; no provider call."},"429":{"description":"Per-account rate limit."},"503":{"description":"Sources or bounded request unavailable. Private diagnostics are omitted."}}}},"/api/courses/{courseId}/academy-learning-consent":{"get":{"tags":["Course Learning"],"summary":"Account bearer owner only: current apply-consent metadata. No private snapshot or reusable credential.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/academy-learning-consent/challenge":{"post":{"tags":["Course Learning"],"summary":"Explicit independent apply consent after a current verified preview. Ten-minute hash-only code; does not start or freeze learning.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["previewId","confirm"],"properties":{"previewId":{"type":"string","maxLength":160},"confirm":{"const":true}}}}}},"responses":{"201":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/academy-learning-consent/cancel":{"post":{"tags":["Course Learning"],"summary":"Revoke future consent checks, also with flags off. Does not undo an existing operation or unfreeze its source; use operation recovery.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["confirm"],"properties":{"confirm":{"const":true}}}}}},"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/academy-learning":{"get":{"tags":["Course Learning"],"summary":"Account bearer owner only: latest durable operation, including recovery after a lost response. Available with flags off; no private source rows.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}},"post":{"tags":["Course Learning"],"summary":"Explicitly apply independently approved learning migration. Prepare native writer, freeze/read source, atomically import, and acknowledge the signed result. Does not activate the full account.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["consentId","receipt","confirm"],"properties":{"consentId":{"type":"string","maxLength":160},"receipt":{"type":"string","pattern":"^amap_[A-Za-z0-9_-]{43}$","writeOnly":true},"confirm":{"const":true}}}}}},"responses":{"200":{"description":"Success"},"202":{"description":"Durable operation requires recovery; not a successful full account cutover"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/academy-learning-consent/inspect":{"post":{"tags":["Course Learning"],"summary":"Purpose-bound private metadata backchannel. Rejects Origin, Cookie and Authorization; an opaque credential is required and hashes do not authorize a source freeze.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["code"],"properties":{"code":{"type":"string","pattern":"^amac_[A-Za-z0-9_-]{43}$","writeOnly":true}}}}}},"responses":{"200":{"description":"Bound private metadata, no-store"},"400":{"description":"Invalid JSON"},"403":{"description":"Inactive or unknown consent"},"404":{"description":"Disabled"},"405":{"description":"POST required"},"413":{"description":"Body limit exceeded"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Storage or recovery key unavailable"}}}},"/api/courses/academy-learning-consent/active":{"post":{"tags":["Course Learning"],"summary":"Purpose-bound private metadata backchannel. Rejects Origin, Cookie and Authorization; an opaque credential is required and hashes do not authorize a source freeze.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["id","challengeHash"],"properties":{"id":{"type":"string","maxLength":160},"challengeHash":{"type":"string","pattern":"^[a-f0-9]{64}$","writeOnly":true}}}}}},"responses":{"200":{"description":"Bound private metadata, no-store"},"400":{"description":"Invalid JSON"},"403":{"description":"Inactive or unknown consent"},"404":{"description":"Disabled"},"405":{"description":"POST required"},"413":{"description":"Body limit exceeded"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Storage or recovery key unavailable"}}}},"/api/courses/academy-learning/prepared":{"post":{"tags":["Course Learning"],"summary":"Purpose-bound private metadata backchannel. Rejects Origin, Cookie and Authorization; an opaque credential is required and hashes do not authorize a source freeze.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["cutoverId","receipt"],"properties":{"cutoverId":{"type":"string","maxLength":160},"receipt":{"type":"string","pattern":"^amap_[A-Za-z0-9_-]{43}$","writeOnly":true}}}}}},"responses":{"200":{"description":"Bound private metadata, no-store"},"400":{"description":"Invalid JSON"},"403":{"description":"Inactive or unknown consent"},"404":{"description":"Disabled"},"405":{"description":"POST required"},"413":{"description":"Body limit exceeded"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Storage or recovery key unavailable"}}}},"/api/courses/{courseId}/academy-learning/{cutoverId}":{"get":{"tags":["Course Learning"],"summary":"Account bearer owner only: read an existing learning cutover. No create, import or activation. Recovery remains available when rollout flags are off.","security":[{"BearerAuth":[]}],"description":"Requires the original account bearer session and exact operation ownership, not current lesson access or an active account link. Cookie-only sessions, course agents and service keys are not accepted. Recovery remains available with issuance flags off. No create, import, activation or new learning writes.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"cutoverId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Operation unavailable for this account and course"},"405":{"description":"Method not allowed"},"409":{"description":"Terminal outcome conflict or unresolved source acknowledgement"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/academy-learning/{cutoverId}/abort":{"post":{"tags":["Course Learning"],"summary":"Explicitly cancel a prepared learning cutover under the import owner lock. A committed import can never be aborted. No implicit source unfreeze.","security":[{"BearerAuth":[]}],"description":"Requires the original account bearer session and exact operation ownership, not current lesson access or an active account link. Cookie-only sessions, course agents and service keys are not accepted. Recovery remains available with issuance flags off. No create, import, activation or new learning writes.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"cutoverId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["confirm"],"properties":{"confirm":{"const":true}}}}}},"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Operation unavailable for this account and course"},"405":{"description":"Method not allowed"},"409":{"description":"Terminal outcome conflict or unresolved source acknowledgement"},"413":{"description":"Request exceeds 1024 bytes"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/academy-learning/{cutoverId}/settle":{"post":{"tags":["Course Learning"],"summary":"Send only the verified signed terminal outcome to the fixed source Academy. Retry resolves a lost response without copying learner data again. Source acknowledgement is not full account activation.","security":[{"BearerAuth":[]}],"description":"Requires the original account bearer session and exact operation ownership, not current lesson access or an active account link. Cookie-only sessions, course agents and service keys are not accepted. Recovery remains available with issuance flags off. No create, import, activation or new learning writes.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"cutoverId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["confirm"],"properties":{"confirm":{"const":true}}}}}},"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Operation unavailable for this account and course"},"405":{"description":"Method not allowed"},"409":{"description":"Terminal outcome conflict or unresolved source acknowledgement"},"413":{"description":"Request exceeds 1024 bytes"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/academy-transfer":{"get":{"tags":["Course Learning"],"summary":"Account bearer session only: latest aggregate migration preview and current link status. No private snapshot or reusable credential.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}},"delete":{"tags":["Course Learning"],"summary":"Account bearer session only: cancel preview consent, including during rollback. Does not delete learning data.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/academy-transfer/challenge":{"post":{"tags":["Course Learning"],"summary":"Separate explicit consent for a read-only migration preview. Hash-only ten-minute code, never a link receipt. New issuance cancels the previous preview.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["confirm"],"properties":{"confirm":{"const":true}}}}}},"responses":{"201":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/academy-transfer/preview":{"post":{"tags":["Course Learning"],"summary":"Verify source consent through fixed HTTPS and recheck the active native link before saving an aggregate report. No progress, role, mail or history import. Replays return the same report.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["challengeId","receipt","confirm"],"properties":{"challengeId":{"type":"string","maxLength":160},"receipt":{"type":"string","pattern":"^amxp_[A-Za-z0-9_-]{43}$","writeOnly":true},"confirm":{"const":true}}}}}},"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"422":{"description":"Source snapshot cannot be reconciled against the configured exact course content"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/academy-transfer/inspect":{"post":{"tags":["Course Learning"],"summary":"Opaque-challenge backchannel: purpose-bound active preview metadata. Rejects browser origins, cookies and authorization headers; no learner snapshot or claim of caller-origin authentication.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["code"],"properties":{"code":{"type":"string","pattern":"^amxc_[A-Za-z0-9_-]{43}$","writeOnly":true}}}}}},"responses":{"200":{"description":"Exact bound metadata, private no-store"},"400":{"description":"Invalid JSON"},"403":{"description":"Inactive or unknown consent"},"404":{"description":"Disabled"},"405":{"description":"POST required"},"413":{"description":"Body over 4096 bytes"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Storage unavailable"}}}},"/api/courses/academy-transfer/active":{"post":{"tags":["Course Learning"],"summary":"Opaque-challenge backchannel: purpose-bound active preview metadata. Rejects browser origins, cookies and authorization headers; no learner snapshot or claim of caller-origin authentication.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["id","challengeHash"],"properties":{"id":{"type":"string","maxLength":160},"challengeHash":{"type":"string","pattern":"^[a-f0-9]{64}$","writeOnly":true}}}}}},"responses":{"200":{"description":"Exact bound metadata, private no-store"},"400":{"description":"Invalid JSON"},"403":{"description":"Inactive or unknown consent"},"404":{"description":"Disabled"},"405":{"description":"POST required"},"413":{"description":"Body over 4096 bytes"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Storage unavailable"}}}},"/api/courses/{courseId}/current":{"get":{"tags":["Course Learning"],"summary":"Resolve the current published release by exact course ID, not slug. An authenticated course-scoped agent may use this read.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/academy-account-link":{"get":{"tags":["Course Learning"],"summary":"Account session only: own Academy migration binding and pending challenge metadata, never raw secrets; readable during rollback.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}},"delete":{"tags":["Course Learning"],"summary":"Account bearer session only: cancel pending challenges and revoke future migration consent. Does not erase learner history or silently rebind identities; works during rollback.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/academy-account-link/challenge":{"post":{"tags":["Course Learning"],"summary":"Account bearer session only: explicitly issue a ten-minute challenge once. A repeated key returns 409; a new request cancels earlier pending challenges.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["confirm"],"properties":{"confirm":{"const":true}}}}}},"responses":{"201":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/academy-account-link/confirm":{"post":{"tags":["Course Learning"],"summary":"Account bearer session only: consume a challenge after fixed-origin source proof verification. Replays cannot restore revoked consent; no email matching or role transfer.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["challengeId","receipt","confirm"],"properties":{"challengeId":{"type":"string","maxLength":160},"receipt":{"type":"string","pattern":"^amlp_[A-Za-z0-9_-]{43}$","writeOnly":true},"confirm":{"const":true}}}}}},"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/academy-account-link/inspect":{"post":{"tags":["Course Learning"],"summary":"Possession of the opaque challenge permits inspection of the exact migration destination only. No email, session, roles or learning data.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["code"],"properties":{"code":{"type":"string","pattern":"^amlc_[A-Za-z0-9_-]{43}$","writeOnly":true}}}}}},"responses":{"200":{"description":"Purpose-bound challenge metadata, private no-store"},"400":{"description":"Invalid JSON"},"403":{"description":"Expired, revoked, consumed or unknown challenge"},"404":{"description":"Disabled"},"405":{"description":"POST required"},"413":{"description":"Body over 4096 bytes"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Storage unavailable"}}}},"/api/courses/{courseId}/notification-preferences":{"get":{"tags":["Course Learning"],"summary":"Account session only: current course news and separate learning-mail preferences, never a token or recipient email","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}},"put":{"tags":["Course Learning"],"summary":"Account session only: versioned explicit preferences; unsubscribe remains possible after course access is revoked","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["news","learning","version"],"properties":{"news":{"type":"boolean"},"learning":{"type":"boolean"},"version":{"type":"integer","minimum":0,"maximum":2147483646}}}}}},"responses":{"200":{"description":"Idempotent replay"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/notifications/unsubscribe":{"post":{"tags":["Course Learning"],"summary":"Explicitly unsubscribe from both course mail streams using an opaque email-link token; works during feature rollback","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["token"],"properties":{"token":{"type":"string","maxLength":80,"writeOnly":true},"requestId":{"type":"string","pattern":"^anu_[a-f0-9]{64}$","description":"Optional legacy Academy relay event. Repeating it acknowledges the first application without replacing later explicit preferences. Valid only with an imported legacy unsubscribe token."}}}}}},"responses":{"200":{"description":"Opt-out accepted, including acknowledged event replay"},"400":{"description":"Invalid body"},"404":{"description":"Unknown link"},"405":{"description":"Only POST changes preferences"},"409":{"description":"Idempotency conflict"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Database unavailable"}}}},"/api/courses/{courseId}/agent-connections":{"get":{"tags":["Course Learning"],"summary":"Account session only: list your course connections without secrets; active connections first, latest 100 records.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}},"post":{"tags":["Course Learning"],"summary":"Account session only: explicitly issue a one-time, course-scoped credential. Repeating the same request returns 409, never the secret again.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":80},"scope":{"enum":["course_read","course_study"],"default":"course_read"},"expiresInDays":{"type":"integer","minimum":1,"maximum":30,"default":14}}}}}},"responses":{"201":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/agent-connections/{connectionId}":{"delete":{"tags":["Course Learning"],"summary":"Account session only: revoke your course connection. Repeat returns success without another event; saved learner state is retained.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"connectionId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/agent-setup":{"get":{"tags":["Course Learning"],"summary":"Account bearer session only: latest 100 setup grant metadata records. Reads and cancellation remain available with issuance disabled.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}},"post":{"tags":["Course Learning"],"summary":"Explicit ten-minute, hash-only course setup grant; no connection is created yet. A lost code is not replayed.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name","scope","expiresInDays","confirm"],"properties":{"name":{"type":"string","minLength":1,"maxLength":80},"scope":{"enum":["course_read","course_study"]},"expiresInDays":{"type":"integer","minimum":1,"maximum":30},"confirm":{"const":true}}}}}},"responses":{"201":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/agent-setup/{setupId}":{"delete":{"tags":["Course Learning"],"summary":"Cancel the setup grant and revoke its resulting connection, including a concurrent exchange. Saved learning work remains.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"setupId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/agent-setup/exchange":{"post":{"tags":["Course Learning"],"summary":"Exchange one exact course setup code once, after explicit client scope confirmation; no account bearer is forwarded.","security":[],"description":"Code-only POST, 1 KiB body, no redirects or bearer Authorization. Ten-minute expiry, fresh issuing session and course access, one atomic consume/key creation. Repeated exchange never returns another key. Feature-off stops exchange. Response is private/no-store; never log code or token. Installation remains an explicit client action.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["code","scope","confirm"],"properties":{"code":{"type":"string","pattern":"^atlcs_[A-Za-z0-9_-]{43}$","writeOnly":true},"scope":{"enum":["course_read","course_study"]},"confirm":{"const":true}}}}}},"responses":{"201":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/invitations/accept":{"post":{"tags":["Course Learning"],"summary":"Explicitly accept a one-use course invitation after authentication; retry never restores revoked membership","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["code"],"properties":{"code":{"type":"string","pattern":"^aci_[a-zA-Z0-9_-]{43}$","writeOnly":true}}}}}},"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/releases/{releaseId}/materials/{materialId}/study":{"get":{"tags":["Course Learning"],"summary":"Read versioned study position, artifact revision and server-derived completion","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"materialId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}},"put":{"tags":["Course Learning"],"summary":"Save study position without completing a lesson","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"materialId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["assessmentVersion","stage","section","caseChoice"],"properties":{"assessmentVersion":{"type":"integer","minimum":1,"maximum":2147483647},"stage":{"type":"string","enum":["case","reading","practice","quiz","resources"]},"section":{"type":"integer","minimum":0},"caseChoice":{"type":["integer","null"],"minimum":0}}}}}},"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/releases/{releaseId}/materials/{materialId}/artifact":{"put":{"tags":["Course Learning"],"summary":"Save non-empty text, preserving whitespace, up to 24000 UTF-16 units and an optional private reference under one compare-and-swap revision. Omitted URL preserves it; null clears it. URL alone cannot complete the artifact. A migration fence returns 409 without saving.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"materialId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["assessmentVersion","body","revision"],"properties":{"assessmentVersion":{"type":"integer","minimum":1,"maximum":2147483647},"body":{"type":"string","minLength":1,"maxLength":24000},"url":{"type":["string","null"],"maxLength":2000,"pattern":"^https://[^@\\s]+$"},"revision":{"type":"integer","minimum":0}}}}}},"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/releases/{releaseId}/materials/{materialId}/quiz-attempts":{"post":{"tags":["Course Learning"],"summary":"Grade an idempotent quiz attempt on the server","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"materialId","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["assessmentVersion","answers"],"properties":{"assessmentVersion":{"type":"integer","minimum":1,"maximum":2147483647},"locale":{"type":"string"},"answers":{"type":"object","additionalProperties":{"type":"integer","minimum":0,"maximum":7}}}}}}},"responses":{"200":{"description":"Idempotent replay"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}},"get":{"tags":["Course Learning"],"summary":"Read your private scored attempts across assessment versions, newest first; fresh access to the current lesson is required. No answers, artifacts or grading keys.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"materialId","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}},{"name":"after","in":"query","schema":{"type":"string"},"description":"Opaque next cursor from the preceding history page."}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/start":{"post":{"tags":["Course Learning"],"summary":"Start the first accessible lesson","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/progress":{"get":{"tags":["Course Learning"],"summary":"Read retained course progress","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/releases/{releaseId}/library":{"get":{"tags":["Course Learning"],"summary":"List template summaries from currently authorized lessons; no template bodies","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/releases/{releaseId}/library/{templateId}":{"get":{"tags":["Course Learning"],"summary":"Read an authorized template from its immutable lesson block","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"templateId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/releases/{releaseId}/resources":{"get":{"tags":["Course Learning"],"summary":"Read authorized course resources; optional lessonId filter and locale. Requires login, current release and fresh resource access; related lesson links are independently filtered.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/releases/{releaseId}/materials/{materialId}/progress":{"put":{"tags":["Course Learning"],"summary":"Save learner progress","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"materialId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["state"],"properties":{"state":{"type":"string","enum":["not_started","in_progress","completed"]},"positionSeconds":{"type":["integer","null"],"minimum":0,"maximum":86400}}}}}},"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/releases/{releaseId}/materials/{materialId}/note":{"get":{"tags":["Course Learning"],"summary":"Read your private lesson note","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"materialId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}},"put":{"tags":["Course Learning"],"summary":"Save your private lesson note","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"materialId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["note"],"properties":{"note":{"type":"string","minLength":1,"maxLength":20000}}}}}},"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}},"delete":{"tags":["Course Learning"],"summary":"Delete your private lesson note","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"materialId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/releases/{releaseId}/tasks/{taskId}/submissions":{"post":{"tags":["Course Learning"],"summary":"Submit task evidence","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"taskId","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"required":["evidence"],"properties":{"evidence":{"description":"Non-null JSON evidence, at most 100000 UTF-8 bytes when serialized."}}}}}},"responses":{"200":{"description":"Idempotent replay"},"201":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/releases/{releaseId}/materials/{materialId}/playback-session":{"post":{"tags":["Course Learning"],"summary":"Request authorized video playback","security":[{},{"BearerAuth":[]}],"description":"Anonymous access is permitted only for public materials. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"materialId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/releases/{releaseId}/materials/{materialId}/download-session":{"post":{"tags":["Course Learning"],"summary":"Request an authorized material download","security":[{},{"BearerAuth":[]}],"description":"Anonymous access is permitted only for public materials. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"materialId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/releases/{releaseId}/agent/query":{"post":{"tags":["Course Learning"],"summary":"Ask over accessible course material. Optional lesson scope; saveHistory requires the feature flag, an explicit session and Idempotency-Key. Fresh access to every supplied excerpt is checked again before returning text.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Required when saveHistory=true; reuse only for a retry of exactly the same question, lesson and release.","schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,160}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["query"],"properties":{"query":{"type":"string","minLength":1,"maxLength":2000},"materialId":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_.:-]{0,159}$"},"saveHistory":{"type":"boolean","default":false}}}}}},"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"410":{"description":"Saved request was erased or expired; no answer returned."},"413":{"description":"JSON body exceeds 16 KiB."},"429":{"description":"Rate limit exceeded"},"502":{"description":"Provider failed or cited unauthorized chunks. The rejected answer is never returned; only re-authorized source excerpts may be supplied as search_only fallback."},"503":{"description":"Storage or provider unavailable. With authorized context, mode=search_only supplies original excerpts and exact citations, never a fabricated or saved answer."}}}},"/api/courses/{courseId}/agent/history":{"get":{"tags":["Course Learning"],"summary":"Read your private assistant history, newest first. Expired text is never returned; changed releases or lost access hide the whole turn. Available even if saving is disabled.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"materialId","in":"query","schema":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_.:-]{0,159}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}},{"name":"after","in":"query","schema":{"type":"string"},"description":"Opaque next-page cursor."}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}},"delete":{"tags":["Course Learning"],"summary":"Erase all your saved and pending course assistant turns. Explicit session required; works after course access is revoked and during feature rollback.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/agent/history/{turnId}":{"delete":{"tags":["Course Learning"],"summary":"Erase one owned turn. No answer is retained; a content-free replay tombstone lasts only until the original expiry. Explicit session required.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"turnId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/agent/history/academy":{"get":{"tags":["Course Learning"],"summary":"List your imported Academy threads. Separate default-off read gate, full activation and every prompt dependency required. Unknown or changed context hides titles and bodies. No Admin or agent access.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}},{"name":"after","in":"query","schema":{"type":"string","maxLength":512}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}},"delete":{"tags":["Course Learning"],"summary":"Erase imported threads and prevent a late initial copy from resurrecting older source history. Explicit session required, independent of feature/access gates.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/api/courses/{courseId}/agent/history/academy/{threadId}":{"get":{"tags":["Course Learning"],"summary":"Read one owned imported thread with original expiry and fresh full-context access. Never reused as assistant prompt context.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"threadId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}},"delete":{"tags":["Course Learning"],"summary":"Erase one owned imported thread, leaving only an expiring content-free tombstone.","security":[{"BearerAuth":[]}],"description":"Requires an authenticated learner. Platform checks access to the requested release and material. Responses are private and must not be cached.","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"threadId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid request body or idempotency key"},"401":{"description":"Authentication required"},"403":{"description":"Material access denied"},"404":{"description":"Release or material not found"},"409":{"description":"Operation not applicable to this material or conflicting submission"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Required storage or provider unavailable"}}}},"/go/{code}":{"get":{"tags":["Attribution"],"summary":"Resolve one active content campaign tracking link","security":[],"parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{3,96}$"}}],"responses":{"302":{"description":"Allowlisted immutable destination version"},"404":{"description":"Tracking link not found"},"410":{"description":"Tracking link unavailable"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Tracking link service unavailable"}}},"head":{"tags":["Attribution"],"summary":"Check one active tracking redirect without recording a touch","security":[],"parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{3,96}$"}}],"responses":{"302":{"description":"Allowlisted immutable destination version without attribution capture"},"404":{"description":"Tracking link not found"},"410":{"description":"Tracking link unavailable"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Tracking link service unavailable"}}}},"/claim/{token}":{"get":{"tags":["Attribution"],"summary":"Exchange a short-lived social claim token for a protected first-party cookie","security":[],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"303":{"description":"Claim cookie set and redirected to the clean signup URL"},"404":{"description":"Unknown claim"},"409":{"description":"Claim already consumed by another account"},"410":{"description":"Expired claim"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Claim service unavailable"}}}},"/api/core/workspaces":{"get":{"tags":["Core"],"summary":"List Core workspaces visible to the authenticated user","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Workspace list"},"401":{"description":"Authentication required"}}},"post":{"tags":["Core"],"summary":"Create a Core workspace and owner membership","security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["slug","name"],"properties":{"slug":{"type":"string"},"name":{"type":"string"}}}}}},"responses":{"201":{"description":"Workspace created"},"401":{"description":"Authentication required"},"409":{"description":"Slug conflict"},"413":{"description":"Request body too large"}}}},"/api/core/workspaces/{workspaceId}/dossiers":{"get":{"tags":["Core"],"summary":"List task dossiers in one authorized workspace","security":[{"BearerAuth":[]}],"parameters":[{"name":"workspaceId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Dossier list"},"401":{"description":"Authentication required"},"404":{"description":"Workspace not visible"}}},"post":{"tags":["Core"],"summary":"Persist a validated Core task dossier","security":[{"BearerAuth":[]}],"description":"Requires an Idempotency-Key header. New task dossiers must use revision 1.","parameters":[{"name":"workspaceId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["document"],"properties":{"document":{"type":"object","additionalProperties":true}}}}}},"responses":{"201":{"description":"Dossier created"},"401":{"description":"Authentication required"},"403":{"description":"Editor or owner role required"},"409":{"description":"Identity or idempotency conflict"},"413":{"description":"Request body too large"},"422":{"description":"Core contract rejected"}}}},"/api/core/workspaces/{workspaceId}/dossiers/{dossierId}":{"get":{"tags":["Core"],"summary":"Get one authorized task dossier","security":[{"BearerAuth":[]}],"parameters":[{"name":"workspaceId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"dossierId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Dossier and current ETag"},"401":{"description":"Authentication required"},"404":{"description":"Dossier not visible"}}},"put":{"tags":["Core"],"summary":"Write the next validated dossier revision","security":[{"BearerAuth":[]}],"description":"Requires exact If-Match and Idempotency-Key headers. The Core document revision must increment by one.","parameters":[{"name":"workspaceId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"dossierId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"If-Match","in":"header","required":true,"schema":{"type":"integer","minimum":1}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["document"],"properties":{"document":{"type":"object","additionalProperties":true},"status":{"type":"string","enum":["draft","ready","archived"]}}}}}},"responses":{"200":{"description":"Dossier updated"},"401":{"description":"Authentication required"},"403":{"description":"Editor or owner role required"},"409":{"description":"Version or idempotency conflict"},"413":{"description":"Request body too large"},"422":{"description":"Core contract rejected"}}}},"/api/core/workspaces/{workspaceId}/workflow-releases":{"post":{"tags":["Core"],"summary":"Import an immutable Core v0.2 workflow module release","security":[{"BearerAuth":[]}],"description":"Feature-off unless CORE_V02_ARTIFACTS_ENABLED=true. Requires workspace editor access and Idempotency-Key.","parameters":[{"name":"workspaceId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["document"],"properties":{"document":{"type":"object","additionalProperties":true}}}}}},"responses":{"200":{"description":"Identical immutable release replayed"},"201":{"description":"Release imported"},"401":{"description":"Authentication required"},"403":{"description":"Editor or owner role required"},"409":{"description":"Identity or idempotency conflict"},"413":{"description":"Request body too large"},"422":{"description":"Core contract rejected"},"503":{"description":"Feature disabled"}}}},"/api/core/workspaces/{workspaceId}/workflow-releases/{moduleId}/{version}":{"get":{"tags":["Core"],"summary":"Get an exact immutable workflow module release","security":[{"BearerAuth":[]}],"description":"Feature-off unless CORE_V02_ARTIFACTS_ENABLED=true.","parameters":[{"name":"workspaceId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"moduleId","in":"path","required":true,"schema":{"type":"string"}},{"name":"version","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Exact release"},"401":{"description":"Authentication required"},"404":{"description":"Workspace or release not visible"},"503":{"description":"Feature disabled"}}}},"/api/core/workspaces/{workspaceId}/routes":{"post":{"tags":["Core"],"summary":"Import an immutable Core v0.2 pinned route","security":[{"BearerAuth":[]}],"description":"Validates the route against exact stored dossier and release pins without network or model calls.","parameters":[{"name":"workspaceId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["document"],"properties":{"document":{"type":"object","additionalProperties":true}}}}}},"responses":{"200":{"description":"Identical route replayed"},"201":{"description":"Route imported"},"401":{"description":"Authentication required"},"403":{"description":"Editor or owner role required"},"409":{"description":"Identity or idempotency conflict"},"413":{"description":"Request body too large"},"422":{"description":"Pinned dependency or composition rejected"},"503":{"description":"Feature disabled"}}}},"/api/core/workspaces/{workspaceId}/routes/{routeId}":{"get":{"tags":["Core"],"summary":"Get an immutable pinned route","security":[{"BearerAuth":[]}],"description":"Feature-off unless CORE_V02_ARTIFACTS_ENABLED=true.","parameters":[{"name":"workspaceId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"routeId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Pinned route"},"401":{"description":"Authentication required"},"404":{"description":"Workspace or route not visible"},"503":{"description":"Feature disabled"}}}},"/api/core/workspaces/{workspaceId}/decision-packs":{"post":{"tags":["Core"],"summary":"Import an immutable recomposed Decision Pack","security":[{"BearerAuth":[]}],"description":"Recomposes the pack from exact stored pins and requires canonical equality before insertion.","parameters":[{"name":"workspaceId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["document"],"properties":{"document":{"type":"object","additionalProperties":true}}}}}},"responses":{"200":{"description":"Identical Decision Pack replayed"},"201":{"description":"Decision Pack imported"},"401":{"description":"Authentication required"},"403":{"description":"Editor or owner role required"},"409":{"description":"Identity or idempotency conflict"},"413":{"description":"Request body too large"},"422":{"description":"Recomposition or pinned dependency rejected"},"503":{"description":"Feature disabled"}}}},"/api/core/workspaces/{workspaceId}/decision-packs/{decisionPackId}":{"get":{"tags":["Core"],"summary":"Get an immutable Decision Pack","security":[{"BearerAuth":[]}],"description":"Feature-off unless CORE_V02_ARTIFACTS_ENABLED=true.","parameters":[{"name":"workspaceId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"decisionPackId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Decision Pack"},"401":{"description":"Authentication required"},"404":{"description":"Workspace or Decision Pack not visible"},"503":{"description":"Feature disabled"}}}},"/api/courses":{"get":{"tags":["Courses"],"summary":"List published Courses with resource-scoped lock states","security":[],"parameters":[{"name":"locale","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Published Course outlines","content":{"application/json":{"schema":{"type":"object","properties":{"contractVersion":{"type":"integer","const":1},"items":{"type":"array","items":{"oneOf":[{"$ref":"#/components/schemas/CourseOutline"},{"$ref":"#/components/schemas/CourseOutlineV2"}]}}}}}}}}}},"/api/courses/{slug}":{"get":{"tags":["Courses"],"summary":"Get one published Course outline","security":[],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}},{"name":"locale","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Course v1 or localized v2/v3 outline","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/CourseOutline"},{"$ref":"#/components/schemas/CourseOutlineV2"}]}}}},"404":{"description":"Course not found"}}}},"/api/courses/{courseId}/releases/{releaseId}/materials/{materialId}":{"get":{"tags":["Courses"],"summary":"Get one exact-release material after server-side access decision","security":[],"parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"materialId","in":"path","required":true,"schema":{"type":"string"}},{"name":"locale","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Authorized v1 material or localized v2 lesson with explicit locale fallback marker"},"401":{"description":"Sign-in required, locked metadata only"},"403":{"description":"Locked metadata only, without blocks, asset IDs, checksums, or URLs"},"404":{"description":"Material or release not found"}}}},"/api/courses/{courseId}/releases/{releaseId}/materials/{materialId}/assets/{assetId}/delivery-session":{"post":{"operationId":"createCourseMaterialAssetDeliverySession","tags":["Courses"],"summary":"Issue a short-lived delivery session for one canonical authorized material asset","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"materialId","in":"path","required":true,"schema":{"type":"string"}},{"name":"assetId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["purpose"],"properties":{"purpose":{"type":"string","enum":["inline","attachment"]}}}}}},"responses":{"201":{"description":"Short-lived clean and published asset delivery"},"401":{"description":"Authentication required without asset disclosure"},"403":{"description":"Material locked without asset disclosure"},"404":{"description":"Asset is not referenced by this canonical material"},"409":{"description":"Asset is not ready"}}}},"/api/courses/{courseId}/releases/{releaseId}/assets/{assetId}/delivery-session":{"post":{"operationId":"createCourseReleaseAssetDeliverySession","tags":["Courses"],"summary":"Issue a short-lived delivery session for the canonical Course cover or author avatar","parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"assetId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["purpose"],"properties":{"purpose":{"type":"string","enum":["inline","attachment"]}}}}}},"responses":{"201":{"description":"Short-lived delivery with courseId, releaseId, assetId, purpose, and delivery"},"403":{"description":"No accessible material in this exact release"},"404":{"description":"Asset is not this release's cover or author avatar"},"409":{"description":"Asset is not ready"}}}},"/api/pulse/home":{"get":{"tags":["Pulse"],"summary":"Get the bounded AtlasRepo home Pulse preview","description":"Returns up to six real published items per section. Empty and unavailable sources are represented explicitly and never replaced with fabricated cards.","security":[],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":4,"minimum":1,"maximum":6}}],"responses":{"200":{"description":"Home Pulse projection","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PulseResponse"}}}},"503":{"description":"Database is not configured"}}}},"/api/pulse":{"get":{"tags":["Pulse"],"summary":"Get the full AtlasRepo Pulse projection","description":"Returns independent repository, news, workflow, template, skill, MCP, model and AI-company sections with exact totals, watermarks, and per-section cursors. Individual source failures produce a partial response with an unavailable section.","security":[],"parameters":[{"name":"types","in":"query","description":"Comma-separated section names","schema":{"type":"string","example":"repositories,news,skills"}},{"name":"limit","in":"query","schema":{"type":"integer","default":12,"minimum":1,"maximum":50}},{"name":"repositories_cursor","in":"query","schema":{"type":"integer","minimum":0}},{"name":"news_cursor","in":"query","schema":{"type":"integer","minimum":0}},{"name":"workflows_cursor","in":"query","schema":{"type":"integer","minimum":0}},{"name":"templates_cursor","in":"query","schema":{"type":"integer","minimum":0}},{"name":"skills_cursor","in":"query","schema":{"type":"integer","minimum":0}},{"name":"mcp_cursor","in":"query","schema":{"type":"integer","minimum":0}},{"name":"models_cursor","in":"query","schema":{"type":"integer","minimum":0}},{"name":"ai_companies_cursor","in":"query","schema":{"type":"integer","minimum":0}}],"responses":{"200":{"description":"Pulse projection","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PulseResponse"}}}},"400":{"description":"Unknown section in types"},"503":{"description":"Database is not configured"}}}},"/api/content/blog-posts":{"get":{"tags":["Content"],"summary":"List published AtlasRepo blog articles","security":[],"responses":{"200":{"description":"Published article summaries"}}}},"/api/content/blog-posts/{slug}":{"get":{"tags":["Content"],"summary":"Get one published blog article","security":[],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"}}],"responses":{"200":{"description":"Published article with source and editorial metadata"},"404":{"description":"Not found"}}}},"/api/scout-feed":{"get":{"tags":["Catalog"],"summary":"Public hourly Scout feed preview","description":"Returns the full enriched feed by default. Pass `view=light` for the trimmed landing variant (card + localized descriptions only, without the verbose enrichment fields). Both variants are gzip/Brotli-compressed and support ETag/If-None-Match conditional GET.","security":[],"parameters":[{"name":"view","in":"query","required":false,"schema":{"type":"string","enum":["full","light"],"default":"full"},"description":"Feed shape. `light` omits enrichment fields for a smaller payload."}],"responses":{"200":{"description":"Scout feed snapshot"}}}},"/api/categories":{"get":{"tags":["Catalog"],"summary":"List Scout categories","description":"Anonymous endpoint returning AtlasRepo category descriptions and active repository counts.","security":[],"responses":{"200":{"description":"Categories with active repository counts","content":{"application/json":{"schema":{"type":"object","required":["items","totalActiveRepos","source"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Category"}},"totalActiveRepos":{"type":"integer","minimum":0},"source":{"type":"string","enum":["postgres","file"]}}}}}}}}},"/api/catalog/top":{"get":{"tags":["Catalog"],"summary":"Public repository catalog page","security":[],"parameters":[{"name":"q","in":"query","schema":{"type":"string"},"description":"Full-text query"},{"name":"niche","in":"query","schema":{"type":"string"}},{"name":"category","in":"query","schema":{"type":"string"}},{"name":"subcategory","in":"query","schema":{"type":"string"},"description":"catalog-page.v2 only: matches categories after the primary category."},{"name":"source","in":"query","schema":{"type":"string"}},{"name":"language","in":"query","schema":{"type":"string"}},{"name":"sort","in":"query","schema":{"type":"string","enum":["score","stars","updated","name"],"default":"score"}},{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"pageSize","in":"query","schema":{"type":"integer","minimum":1,"default":24,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque continuation cursor. Legacy decimal offsets remain accepted."},{"name":"limit","in":"query","schema":{"type":"integer","default":24,"maximum":100},"description":"Backward-compatible alias for pageSize."},{"name":"contract","in":"query","schema":{"type":"string","enum":["catalog-page.v1","catalog-page.v2"],"default":"catalog-page.v1"},"description":"Opt into v2 hierarchical taxonomy. The default v1 envelope remains unchanged."}],"responses":{"200":{"description":"Deterministic catalog-page.v1 or opt-in catalog-page.v2 envelope with exact full filtered totals, full catalog total, facets and continuation cursor. v2 defines categories[0] as the primary category and categories[1..] as subcategories."}}}},"/api/catalog/search":{"get":{"tags":["Catalog"],"summary":"Search the full Scout catalog","description":"Requires a paid API key or active paid session. Free accounts do not receive API access.","parameters":[{"name":"q","in":"query","schema":{"type":"string"},"description":"Keyword query"},{"name":"category","in":"query","schema":{"type":"string"}},{"name":"source","in":"query","schema":{"type":"string"}},{"name":"language","in":"query","schema":{"type":"string"}},{"name":"minScore","in":"query","schema":{"type":"number"}},{"name":"minStars","in":"query","schema":{"type":"integer"}},{"name":"dateFrom","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"dateTo","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"sort","in":"query","schema":{"type":"string","enum":["score","stars","refreshed_at","discovered_at","updated_at"]}},{"name":"limit","in":"query","schema":{"type":"integer","default":25,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque continuation cursor. Legacy decimal offsets remain accepted."}],"responses":{"200":{"description":"catalog-page.v1 results with exact full-DB total, deterministic ordering, URL-page metadata and an opaque nextCursor."},"402":{"description":"Paid API key required"}}}},"/api/catalog/solve":{"post":{"tags":["Catalog"],"summary":"Solve a task against the Scout catalog","security":[],"description":"Uses semantic retrieval plus fail-closed lexical grounding when an embedding provider is configured, then falls back to Postgres full-text keyword ranking when embeddings are unavailable. Ungrounded semantic candidates are omitted instead of being presented as task matches.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["task"],"properties":{"task":{"type":"string","description":"Natural-language task or problem statement"},"limit":{"type":"integer","default":10,"maximum":100},"filters":{"type":"object","additionalProperties":false,"properties":{"category":{"type":"string"},"language":{"type":"string"},"minScore":{"type":"number"},"minStars":{"type":"integer"},"source":{"type":"string"}}}}}}}},"responses":{"200":{"description":"Grounded catalog-solve.v1 matches with whyItFits reasons, matchedTaskTerms, query metadata and an explicit qualityGate. total is returned grounded rows, totalIndexed is the exact eligible full-index population, and candidateCount is the bounded materialized safety window."},"503":{"description":"Database is not configured"}}}},"/api/stories":{"get":{"tags":["Stories"],"summary":"Search published stories","description":"Anonymous/free access returns public stories. Paid keys may request paid/private visibility.","parameters":[{"name":"q","in":"query","schema":{"type":"string"}},{"name":"tag","in":"query","schema":{"type":"string"}},{"name":"type","in":"query","schema":{"type":"string"}},{"name":"dateFrom","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"dateTo","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"pageSize","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"description":"Backward-compatible alias for pageSize."}],"responses":{"200":{"description":"catalog-page.v2 results with server facets, deterministic ordering and the exact full filtered total. The legacy stories and limit fields remain present."}}}},"/api/stories/{slug}":{"get":{"tags":["Stories"],"summary":"Get one story by slug","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Story detail"},"404":{"description":"Not found"}}}},"/api/repos/{owner}/{name}":{"get":{"tags":["Catalog"],"summary":"Get one repository with linked stories","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Repository detail"},"404":{"description":"Not found"}}}},"/api/tools":{"get":{"tags":["Tools"],"summary":"Search normalized tools","parameters":[{"name":"q","in":"query","schema":{"type":"string"}},{"name":"kind","in":"query","schema":{"type":"string"}},{"name":"minQuality","in":"query","schema":{"type":"number"}}],"responses":{"200":{"description":"Tools"}}}},"/api/skills":{"get":{"tags":["Skills"],"summary":"Public published AI-agent skills catalog","description":"Server-paginated catalog of published agent skills. Items include source attribution, license, compatibility, install steps, risk level, score, last verification date and update cadence. Pending, rejected and delisted records are never exposed. The bounded curated catalog is used only when PostgreSQL is not configured; a configured database failure is reported as unavailable instead of silently truncating results.","security":[],"parameters":[{"name":"q","in":"query","schema":{"type":"string"}},{"name":"category","in":"query","schema":{"type":"string"}},{"name":"agent","in":"query","schema":{"type":"string"}},{"name":"tag","in":"query","schema":{"type":"string"}},{"name":"source","in":"query","schema":{"type":"string"}},{"name":"risk","in":"query","schema":{"type":"string","enum":["low","medium","high"]}},{"name":"minScore","in":"query","schema":{"type":"number"}},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":100}},{"name":"page","in":"query","schema":{"type":"integer","minimum":1}},{"name":"pageSize","in":"query","schema":{"type":"integer","default":50,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"catalog-page.v2 published Skills catalog"},"400":{"description":"Invalid or ambiguous pagination"}}}},"/api/skills/{slug}":{"get":{"tags":["Skills"],"summary":"Public published AI-agent skill detail","description":"Returns one published skill card by slug. Pending, rejected and delisted records are never exposed. Curated details are used only when PostgreSQL is not configured.","security":[],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Skill detail"},"404":{"description":"Skill not found"}}}},"/api/ai-companies":{"get":{"tags":["AI Companies"],"summary":"Public managed ready-made AI-company/team configs catalog","description":"Published templates from the Scout catalog. Items include roles, agents, skills, runtime assumptions, env requirements, safety notes, setup steps and manual import/export instructions. Draft, private, rejected, delisted and quarantined records are never returned.","security":[],"parameters":[{"name":"q","in":"query","schema":{"type":"string"}},{"name":"category","in":"query","schema":{"type":"string"}},{"name":"skill","in":"query","schema":{"type":"string"}},{"name":"agent","in":"query","schema":{"type":"string"}},{"name":"role","in":"query","schema":{"type":"string"}},{"name":"runtime","in":"query","schema":{"type":"string"}},{"name":"risk","in":"query","schema":{"type":"string","enum":["low","medium","high"]}},{"name":"page","in":"query","schema":{"type":"integer","minimum":1}},{"name":"pageSize","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":24}},{"name":"limit","in":"query","schema":{"type":"integer","maximum":100}}],"responses":{"200":{"description":"AI companies catalog"}}}},"/api/models":{"get":{"tags":["Models"],"summary":"Public published model catalog","description":"Canonical catalog-page.v2 endpoint backed by Scout PostgreSQL. Private, gated, draft, rejected and delisted models are never returned.","security":[],"parameters":[{"name":"q","in":"query","schema":{"type":"string"}},{"name":"category","in":"query","schema":{"type":"string"}},{"name":"pipeline","in":"query","schema":{"type":"string"}},{"name":"library","in":"query","schema":{"type":"string"}},{"name":"license","in":"query","schema":{"type":"string"}},{"name":"page","in":"query","schema":{"type":"integer","minimum":1}},{"name":"pageSize","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":24}}],"responses":{"200":{"description":"Published models catalog"},"503":{"description":"Scout model catalog is not configured or migrated"}}}},"/api/huggingface/models":{"get":{"tags":["Models"],"summary":"Compatibility alias for the public model catalog","deprecated":true,"security":[],"responses":{"200":{"description":"Same published catalog as /api/models"}}}},"/api/tags":{"get":{"tags":["Stories"],"summary":"List public story tags","security":[],"responses":{"200":{"description":"Tags"}}}},"/api/recommendations":{"post":{"tags":["Stories"],"summary":"Recommend stories for a problem statement","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string"},"limit":{"type":"integer"}}}}}},"responses":{"200":{"description":"Recommended stories"}}}},"/api/account/submissions":{"get":{"tags":["Account"],"summary":"List current user's repo/story submissions","responses":{"200":{"description":"Submissions"},"401":{"description":"Auth required"}}},"post":{"tags":["Account"],"summary":"Submit a repo or story for admin review","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["kind","title","summary"],"properties":{"kind":{"type":"string","enum":["repo","story"]},"title":{"type":"string"},"url":{"type":"string"},"summary":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}}}}}}},"responses":{"201":{"description":"Submission created"}}}},"/api/account/api-key":{"get":{"tags":["Account"],"summary":"List API keys","description":"Free accounts can view this endpoint but cannot create API keys."},"post":{"tags":["Account"],"summary":"Create a paid API key","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"expiresInDays":{"type":["integer","null"],"description":"30, 90, 365, or null for no expiry"},"expiresAt":{"type":["string","null"],"format":"date-time"}}}}}},"responses":{"201":{"description":"API key created"},"402":{"description":"Paid subscription required"}}}},"/api/account/mcp-oauth":{"get":{"tags":["Account"],"summary":"List the authenticated user's MCP OAuth connections and request quota","description":"Connections are restricted to the authenticated user. Quota values describe a request window and are not necessarily monthly.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"User-scoped MCP OAuth connection state and quota","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["state","connections","summary","quota"],"properties":{"state":{"type":"string","enum":["connected","revoked","not_connected"]},"connections":{"type":"array","items":{"$ref":"#/components/schemas/McpOAuthConnection"}},"summary":{"type":"object","additionalProperties":false,"required":["activeCount","revokedCount","totalCount"],"properties":{"activeCount":{"type":"integer","minimum":0},"revokedCount":{"type":"integer","minimum":0},"totalCount":{"type":"integer","minimum":0}}},"quota":{"$ref":"#/components/schemas/RequestQuota"}}}}}},"401":{"description":"Authentication required"}}}},"/api/account/api-key/{id}":{"delete":{"tags":["Account"],"summary":"Revoke one API key","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Key revoked"},"404":{"description":"Key not found"}}}},"/api/account/api-key/{id}/reissue":{"post":{"tags":["Account"],"summary":"Reissue one API key","description":"Revokes the old key and returns a new one-time token.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"New API key created"},"404":{"description":"Key not found"}}}}}}