{"openapi":"3.1.0","info":{"title":"Cursare API","version":"1.0.0","description":"\nCursare Platform is the operating system behind a learning business: it brings content, offers, learners, cohorts, payments, and reporting into one organization-scoped model. The REST API exposes that same model for automations, internal tools, data pipelines, and product integrations.\n\n> The API is not a separate product surface. Actions performed here use the same permissions, records, and business rules as the Cursare app.\n\n## How the Platform fits together\n\n| Resource | What it represents |\n| --- | --- |\n| **Organization** | The security and ownership boundary for every request. |\n| **Content** | A course that can be sold, or reusable material read inside a course. |\n| **Offer** | Price, access, delivery, and enrollment terms for a course. |\n| **Learner** | A person's access and progress inside an organization. |\n| **Cohort** | A dated group with its own schedule, members, tutors, and discussion. |\n\nMost integrations start by reading content and offers, then connect learners, purchases, or insights to another system. Webhooks are the better choice when your integration needs to react to changes instead of polling.\n\n## Make your first request\n\nCreate an organization API key in **Settings → Developer → API keys** and send it as a bearer token:\n\n```bash\ncurl https://api.cursare.com/v1/contents \\\n  --header \"Authorization: Bearer cr_live_…\"\n```\n\nEvery successful response uses a `{ data: … }` envelope. Errors return `{ error: string }`. Keys are scoped to one organization, and requests are limited to **240 reads/min** and **60 writes/min** per key.\n\n## Choose the right surface\n\n- Use **REST** for direct reads and commands from your application.\n- Use **webhooks** for reliable event-driven synchronization.\n- Use **MCP** when an AI assistant needs governed tools instead of unrestricted API access.\n- Use **Download OpenAPI Document** to generate clients or validate requests against the OpenAPI 3.1 contract.\n"},"servers":[{"url":"https://api.cursare.com/v1","description":"Production"}],"security":[{"apiKey":[]}],"tags":[{"name":"Index","description":"Self-describing API index."},{"name":"Organization","description":"Organization profile, members, configuration, audit and credentials."},{"name":"Sales","description":"Purchases, revenue, payouts and refunds."},{"name":"Insights","description":"Organization and per-content academic and financial reporting."},{"name":"Automation","description":"Automation operations."},{"name":"Reports and safety","description":"Reports and safety operations."},{"name":"Minor accounts","description":"Minor accounts operations."},{"name":"Minor safety","description":"Minor safety operations."},{"name":"Offers","description":"Sellable packages, prices, delivery and enrollment terms."},{"name":"Media","description":"Organization-owned images for content covers and learning blocks."},{"name":"Contents","description":"Reusable content: create, configure, compose, publish and delete."},{"name":"Learner delivery","description":"Learner delivery operations."},{"name":"Learner runtime","description":"Learner runtime operations."},{"name":"Learners","description":"Enrollments, approval requests and per-learner progress."},{"name":"Cohorts","description":"Cohort schedules, membership, tutors and discussion."},{"name":"Intake forms","description":"Reusable enrollment-question forms."},{"name":"Campaigns","description":"Discount codes scoped to offers or the whole organization."},{"name":"Teams","description":"Staff teams, memberships and content-domain roles."},{"name":"Affiliates","description":"Native affiliate program, commissions and settlements."},{"name":"Links","description":"Links operations."},{"name":"Reviews","description":"Learner ratings and review feeds."},{"name":"Integrations","description":"Marketing, messaging, tracking, video, payments and assistants."},{"name":"MCP","description":"MCP operations."},{"name":"Webhooks","description":"Signed event destinations, deliveries and test calls."}],"paths":{"/":{"get":{"tags":["Index"],"operationId":"getIndex","summary":"API index","description":"A self-describing index of the API surface for the authenticated org.","responses":{"200":{"description":"API index.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"organization":{"type":"string","description":"The authenticated organization id."},"version":{"type":"string","const":"v1"},"resources":{"type":"object","additionalProperties":{"type":"string"},"description":"Resource group → available routes."}},"required":["organization","version","resources"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/organization":{"get":{"tags":["Organization"],"operationId":"getOrganization","summary":"Get the organization","description":"The API key's organization, with headline usage numbers. WARNING: `usage.revenue` is a size signal, not a quotable amount — it sums the minor units of every currency the org sells in without converting them. Never state it as money; read `listSales` (`revenueByCurrency`) or `getPayouts` instead.","responses":{"200":{"description":"Get the organization.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Organization"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"tags":["Organization"],"operationId":"updateOrganization","summary":"Update the organization","description":"Updates the org's public profile — name, bio, logo, storefront cover — and the checkout tax-id requirement. Only the fields you send are changed. The slug is NOT editable here BY DESIGN: it is the org's subdomain identity (`{slug}` on the root domain), so renaming it breaks every existing link, and it can only be changed from the dashboard. Images must be an https URL or a previously uploaded avatar path.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"bio":{"type":["string","null"],"maxLength":2000,"description":"Free-text about section. Null (or empty) clears it."},"logo":{"description":"An https URL or an uploaded avatar path. Null clears it.","type":["string","null"]},"cover":{"description":"Banner image on the org's public storefront. An https URL or an uploaded avatar path. Null clears it.","type":["string","null"]},"requireCheckoutTaxId":{"description":"When true, buyers must enter a tax id to complete checkout. Turning it on adds friction to every purchase — usually driven by the org's invoicing obligations.","type":"boolean"}}}}}},"responses":{"200":{"description":"Update the organization.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string","description":"The org's subdomain identity — read-only in this API."},"logo":{"type":["string","null"]},"cover":{"description":"Banner image on the org's public storefront.","type":["string","null"]},"bio":{"type":["string","null"]},"requireCheckoutTaxId":{"type":"boolean","description":"Whether checkout demands a buyer tax id."}},"required":["id","name","slug","logo","cover","bio","requireCheckoutTaxId"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/sales":{"get":{"tags":["Sales"],"operationId":"listSales","summary":"Sales totals","description":"Per-content sales totals, net of refunds. Revenue is keyed by currency — never sum across currencies. Every figure is the price paid by buyers. Use `getPayouts` for the corresponding course-payment transfers.","responses":{"200":{"description":"Sales totals.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Sales"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/purchases/{id}/refund":{"post":{"tags":["Sales"],"operationId":"refundPurchase","summary":"Refund a purchase","description":"Persists the refund workflow, issues a full refund on the selling organization's connected Stripe account, revokes access, and marks the purchase refunded only after provider confirmation. Idempotent retries never refund twice.","parameters":[{"name":"id","in":"path","required":true,"description":"The purchase id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Refund a purchase.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"refunded":{"type":"boolean","const":true},"amount":{"type":"integer","description":"The refunded amount in the currency's minor unit (cents)."}},"required":["id","refunded","amount"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/insights":{"get":{"tags":["Insights"],"operationId":"getInsights","summary":"Org-wide insights","description":"Headline academic and financial numbers for the whole org. WARNING: `financial.revenue` is a size signal, not a quotable amount — it sums the minor units of every currency the org sells in without converting them. Never state it as money; read `listSales` (`revenueByCurrency`) or `getPayouts` instead.","responses":{"200":{"description":"Org-wide insights.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Insights"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/automation/execute":{"post":{"tags":["Automation"],"operationId":"executeAutomation","summary":"Execute an automation operation","description":"A narrow gateway for official automation clients. The operation is selected from a closed allowlist, and every call is authenticated, organization-scoped, rate-limited, validated, and authorized by the same application services as the corresponding API resource.","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"operation":{"type":"string","const":"organization.get"},"input":{"type":"object","properties":{}}},"required":["operation","input"]},{"type":"object","properties":{"operation":{"type":"string","const":"content.list"},"input":{"type":"object","properties":{"page":{"default":1,"type":"integer","minimum":1},"pageSize":{"default":25,"type":"integer","minimum":1,"maximum":100}}}},"required":["operation","input"]},{"type":"object","properties":{"operation":{"type":"string","const":"content.get"},"input":{"type":"object","properties":{"contentId":{"type":"string","minLength":1}},"required":["contentId"]}},"required":["operation","input"]},{"type":"object","properties":{"operation":{"type":"string","const":"learner.list"},"input":{"type":"object","properties":{"page":{"default":1,"type":"integer","minimum":1},"pageSize":{"default":25,"type":"integer","minimum":1,"maximum":100}}}},"required":["operation","input"]},{"type":"object","properties":{"operation":{"type":"string","const":"enrollment.create"},"input":{"type":"object","properties":{"contentId":{"type":"string","minLength":1},"email":{"type":"string","format":"email"},"cohortId":{"type":"string","minLength":1}},"required":["contentId","email"]}},"required":["operation","input"]},{"type":"object","properties":{"operation":{"type":"string","const":"enrollment.revoke"},"input":{"type":"object","properties":{"contentId":{"type":"string","minLength":1},"userId":{"type":"string","minLength":1}},"required":["contentId","userId"]}},"required":["operation","input"]},{"type":"object","properties":{"operation":{"type":"string","const":"purchase.list"},"input":{"type":"object","properties":{"page":{"default":1,"type":"integer","minimum":1},"pageSize":{"default":25,"type":"integer","minimum":1,"maximum":100}}}},"required":["operation","input"]},{"type":"object","properties":{"operation":{"type":"string","const":"purchase.get"},"input":{"type":"object","properties":{"purchaseId":{"type":"string","minLength":1}},"required":["purchaseId"]}},"required":["operation","input"]},{"type":"object","properties":{"operation":{"type":"string","const":"webhook.list"},"input":{"type":"object","properties":{}}},"required":["operation","input"]},{"type":"object","properties":{"operation":{"type":"string","const":"webhook.create"},"input":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"events":{"minItems":1,"type":"array","items":{"type":"string","enum":["enrollment.created","enrollment.requested","enrollment.approved","enrollment.rejected","enrollment.expired","learner.unenrolled","content.completed","content.created","content.updated","content.published","content.deleted","offer.created","offer.updated","offer.primary_changed","offer.archived","review.created","review.updated","cohort.created","cohort.updated","cohort.deleted","cohort.joined","cohort.member.moved","cohort.member.removed","discussion.post.created","discussion.post.deleted","discussion.post.resolved","discussion.post.reopened","purchase.created","purchase.installment.paid","purchase.installment.failed","purchase.installment.recovered","purchase.installment.canceled","campaign.redeemed","purchase.refunded","purchase.fee.updated"]}}},"required":["url","events"]}},"required":["operation","input"]},{"type":"object","properties":{"operation":{"type":"string","const":"webhook.delete"},"input":{"type":"object","properties":{"webhookId":{"type":"string","minLength":1}},"required":["webhookId"]}},"required":["operation","input"]}]}}}},"responses":{"200":{"description":"Execute an automation operation.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"result":{"$ref":"#/$defs/__schema0"}},"required":["result"],"$defs":{"__schema0":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"},{"type":"array","items":{"$ref":"#/$defs/__schema0"}},{"type":"object","additionalProperties":{"$ref":"#/$defs/__schema0"}}]}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/safety/cases":{"post":{"tags":["Reports and safety"],"operationId":"createSafetyCase","summary":"Report a trust-and-safety concern","description":"Creates a stable case for an accessible user, content, organization, payment, guardian relationship, or platform concern. Narrative is stored only in the protected case detail.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"targetType":{"type":"string","enum":["user","content","organization","payment","guardian_relationship","platform"]},"targetId":{"type":["string","null"]},"organizationId":{"type":["string","null"]},"category":{"type":"string","enum":["inappropriate_content","harassment_abuse","fraud","privacy","intellectual_property","account_access","child_adolescent_safety","guardian_relationship","other"]},"severity":{"type":"string","enum":["low","medium","high","critical"]},"narrative":{"type":["string","null"],"maxLength":4000}},"required":["targetType","category","severity"]}}}},"responses":{"201":{"description":"Report a trust-and-safety concern.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"get":{"tags":["Reports and safety"],"operationId":"listSafetyCases","summary":"List visible safety cases","description":"Returns a bounded operator collection without reporter narrative, internal notes, evidence, or hidden restricted counts.","parameters":[{"name":"organizationId","in":"query","schema":{"type":"string"}},{"name":"active","in":"query","schema":{"type":"string","enum":["true","false"]}},{"name":"status","in":"query","schema":{"type":"string","enum":["open","triaged","actioned","closed","escalated"]}},{"name":"targetType","in":"query","schema":{"type":"string","enum":["user","content","organization","payment","guardian_relationship","platform"]}},{"name":"category","in":"query","schema":{"type":"string","enum":["inappropriate_content","harassment_abuse","fraud","privacy","intellectual_property","account_access","child_adolescent_safety","guardian_relationship","other"]}},{"name":"sensitivity","in":"query","schema":{"type":"string","enum":["standard","minor_restricted"]}},{"name":"severity","in":"query","schema":{"type":"string","enum":["low","medium","high","critical"]}},{"name":"assignedToUserId","in":"query","schema":{"type":"string"}},{"name":"query","in":"query","schema":{"type":"string","maxLength":100}},{"name":"limit","in":"query","schema":{"default":30,"type":"integer","minimum":1,"maximum":100}},{"name":"subjectKey","in":"query","schema":{"type":"string"}},{"name":"cursorCreatedAt","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"cursorId","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"List visible safety cases.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"organizationId":{"type":["string","null"]},"reporterUserId":{"type":["string","null"]},"subjectUserId":{"type":["string","null"]},"targetType":{"type":"string","enum":["user","content","organization","payment","guardian_relationship","platform"]},"targetId":{"type":["string","null"]},"subjectKey":{"type":"string"},"targetSnapshot":{"type":"object","properties":{"label":{"type":["string","null"]},"secondaryLabel":{"type":["string","null"]},"publicReference":{"type":["string","null"]}}},"category":{"type":"string","enum":["inappropriate_content","harassment_abuse","fraud","privacy","intellectual_property","account_access","child_adolescent_safety","guardian_relationship","other"]},"sensitivity":{"type":"string","enum":["standard","minor_restricted"]},"severity":{"type":"string","enum":["low","medium","high","critical"]},"status":{"type":"string","enum":["open","triaged","actioned","closed","escalated"]},"assignedToUserId":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"closedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","organizationId","reporterUserId","subjectUserId","targetType","targetId","subjectKey","targetSnapshot","category","sensitivity","severity","status","assignedToUserId","createdAt","updatedAt","closedAt"]}},"nextCursor":{"type":["object","null"],"properties":{"createdAt":{"type":"string","format":"date-time"},"id":{"type":"string"}},"required":["createdAt","id"]}},"required":["items","nextCursor"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/safety/cases/{id}/status":{"get":{"tags":["Reports and safety"],"operationId":"getSafetyCaseStatus","summary":"Get the status of a submitted report","parameters":[{"name":"id","in":"path","required":true,"description":"Safety case id returned to the reporter.","schema":{"type":"string"}}],"responses":{"200":{"description":"Get the status of a submitted report.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"targetType":{"type":"string","enum":["user","content","organization","payment","guardian_relationship","platform"]},"targetSnapshot":{"type":"object","properties":{"label":{"type":["string","null"]},"secondaryLabel":{"type":["string","null"]},"publicReference":{"type":["string","null"]}}},"category":{"type":"string","enum":["inappropriate_content","harassment_abuse","fraud","privacy","intellectual_property","account_access","child_adolescent_safety","guardian_relationship","other"]},"severity":{"type":"string","enum":["low","medium","high","critical"]},"status":{"type":"string","enum":["open","triaged","actioned","closed","escalated"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"closedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","targetType","targetSnapshot","category","severity","status","createdAt","updatedAt","closedAt"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/safety/subjects":{"get":{"tags":["Reports and safety"],"operationId":"listSafetySubjects","summary":"List report subjects","description":"Groups only cases visible to the caller by their canonical user, content, organization, payment, guardian-relationship, or platform subject.","parameters":[{"name":"organizationId","in":"query","schema":{"type":"string"}},{"name":"active","in":"query","schema":{"type":"string","enum":["true","false"]}},{"name":"status","in":"query","schema":{"type":"string","enum":["open","triaged","actioned","closed","escalated"]}},{"name":"targetType","in":"query","schema":{"type":"string","enum":["user","content","organization","payment","guardian_relationship","platform"]}},{"name":"category","in":"query","schema":{"type":"string","enum":["inappropriate_content","harassment_abuse","fraud","privacy","intellectual_property","account_access","child_adolescent_safety","guardian_relationship","other"]}},{"name":"sensitivity","in":"query","schema":{"type":"string","enum":["standard","minor_restricted"]}},{"name":"severity","in":"query","schema":{"type":"string","enum":["low","medium","high","critical"]}},{"name":"assignedToUserId","in":"query","schema":{"type":"string"}},{"name":"query","in":"query","schema":{"type":"string","maxLength":100}},{"name":"limit","in":"query","schema":{"default":30,"type":"integer","minimum":1,"maximum":100}},{"name":"minimumVisibleCaseCount","in":"query","schema":{"type":"integer","minimum":1,"maximum":10000}},{"name":"cursorLatestActivity","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"cursorSubjectKey","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"List report subjects.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"subjectKey":{"type":"string"},"organizationId":{"type":["string","null"]},"targetType":{"type":"string","enum":["user","content","organization","payment","guardian_relationship","platform"]},"targetId":{"type":["string","null"]},"targetSnapshot":{"type":"object","properties":{"label":{"type":["string","null"]},"secondaryLabel":{"type":["string","null"]},"publicReference":{"type":["string","null"]}}},"visibleCaseCount":{"type":"integer","minimum":0},"activeCaseCount":{"type":"integer","minimum":0},"highestSeverity":{"type":"string","enum":["low","medium","high","critical"]},"categories":{"type":"array","items":{"type":"string","enum":["inappropriate_content","harassment_abuse","fraud","privacy","intellectual_property","account_access","child_adolescent_safety","guardian_relationship","other"]}},"latestActivity":{"type":"string","format":"date-time"}},"required":["subjectKey","organizationId","targetType","targetId","targetSnapshot","visibleCaseCount","activeCaseCount","highestSeverity","categories","latestActivity"]}},"nextCursor":{"type":["object","null"],"properties":{"latestActivity":{"type":"string","format":"date-time"},"subjectKey":{"type":"string"}},"required":["latestActivity","subjectKey"]}},"required":["items","nextCursor"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/safety/subjects/{subjectKey}/cases":{"get":{"tags":["Reports and safety"],"operationId":"listSafetySubjectCases","summary":"List cases for one report subject","parameters":[{"name":"subjectKey","in":"path","required":true,"description":"Canonical subject key from the subject collection.","schema":{"type":"string"}},{"name":"organizationId","in":"query","schema":{"type":"string"}},{"name":"active","in":"query","schema":{"type":"string","enum":["true","false"]}},{"name":"status","in":"query","schema":{"type":"string","enum":["open","triaged","actioned","closed","escalated"]}},{"name":"targetType","in":"query","schema":{"type":"string","enum":["user","content","organization","payment","guardian_relationship","platform"]}},{"name":"category","in":"query","schema":{"type":"string","enum":["inappropriate_content","harassment_abuse","fraud","privacy","intellectual_property","account_access","child_adolescent_safety","guardian_relationship","other"]}},{"name":"sensitivity","in":"query","schema":{"type":"string","enum":["standard","minor_restricted"]}},{"name":"severity","in":"query","schema":{"type":"string","enum":["low","medium","high","critical"]}},{"name":"assignedToUserId","in":"query","schema":{"type":"string"}},{"name":"query","in":"query","schema":{"type":"string","maxLength":100}},{"name":"limit","in":"query","schema":{"default":30,"type":"integer","minimum":1,"maximum":100}},{"name":"cursorCreatedAt","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"cursorId","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"List cases for one report subject.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"organizationId":{"type":["string","null"]},"reporterUserId":{"type":["string","null"]},"subjectUserId":{"type":["string","null"]},"targetType":{"type":"string","enum":["user","content","organization","payment","guardian_relationship","platform"]},"targetId":{"type":["string","null"]},"subjectKey":{"type":"string"},"targetSnapshot":{"type":"object","properties":{"label":{"type":["string","null"]},"secondaryLabel":{"type":["string","null"]},"publicReference":{"type":["string","null"]}}},"category":{"type":"string","enum":["inappropriate_content","harassment_abuse","fraud","privacy","intellectual_property","account_access","child_adolescent_safety","guardian_relationship","other"]},"sensitivity":{"type":"string","enum":["standard","minor_restricted"]},"severity":{"type":"string","enum":["low","medium","high","critical"]},"status":{"type":"string","enum":["open","triaged","actioned","closed","escalated"]},"assignedToUserId":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"closedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","organizationId","reporterUserId","subjectUserId","targetType","targetId","subjectKey","targetSnapshot","category","sensitivity","severity","status","assignedToUserId","createdAt","updatedAt","closedAt"]}},"nextCursor":{"type":["object","null"],"properties":{"createdAt":{"type":"string","format":"date-time"},"id":{"type":"string"}},"required":["createdAt","id"]}},"required":["items","nextCursor"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/safety/cases/{id}":{"get":{"tags":["Reports and safety"],"operationId":"getSafetyCase","summary":"Get protected safety-case detail","parameters":[{"name":"id","in":"path","required":true,"description":"Safety case id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Get protected safety-case detail.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"organizationId":{"type":["string","null"]},"reporterUserId":{"type":["string","null"]},"subjectUserId":{"type":["string","null"]},"targetType":{"type":"string","enum":["user","content","organization","payment","guardian_relationship","platform"]},"targetId":{"type":["string","null"]},"subjectKey":{"type":"string"},"targetSnapshot":{"type":"object","properties":{"label":{"type":["string","null"]},"secondaryLabel":{"type":["string","null"]},"publicReference":{"type":["string","null"]}}},"category":{"type":"string","enum":["inappropriate_content","harassment_abuse","fraud","privacy","intellectual_property","account_access","child_adolescent_safety","guardian_relationship","other"]},"sensitivity":{"type":"string","enum":["standard","minor_restricted"]},"severity":{"type":"string","enum":["low","medium","high","critical"]},"status":{"type":"string","enum":["open","triaged","actioned","closed","escalated"]},"assignedToUserId":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"closedAt":{"type":["string","null"],"format":"date-time"},"reporterNarrative":{"type":["string","null"]},"internalNotes":{"type":["string","null"]},"resolutionCode":{"type":["string","null"]},"authorityReference":{"type":["string","null"]},"events":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"actorUserId":{"type":["string","null"]},"type":{"type":"string","enum":["created","assigned","status_changed","category_changed","severity_changed","notes_updated","escalated","resolved","closed"]},"details":{"type":"object","additionalProperties":{"type":["string","null"]}},"createdAt":{"type":"string","format":"date-time"}},"required":["id","actorUserId","type","details","createdAt"]}}},"required":["id","organizationId","reporterUserId","subjectUserId","targetType","targetId","subjectKey","targetSnapshot","category","sensitivity","severity","status","assignedToUserId","createdAt","updatedAt","closedAt","reporterNarrative","internalNotes","resolutionCode","authorityReference","events"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"tags":["Reports and safety"],"operationId":"updateSafetyCase","summary":"Triage a safety case","description":"Updates explicit operator fields and appends an immutable sanitized event for every transition.","parameters":[{"name":"id","in":"path","required":true,"description":"Safety case id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["open","triaged","actioned","closed","escalated"]},"category":{"type":"string","enum":["inappropriate_content","harassment_abuse","fraud","privacy","intellectual_property","account_access","child_adolescent_safety","guardian_relationship","other"]},"severity":{"type":"string","enum":["low","medium","high","critical"]},"assignedToUserId":{"type":["string","null"]},"resolutionCode":{"type":["string","null"],"maxLength":100},"authorityReference":{"type":["string","null"],"maxLength":500},"internalNotes":{"type":["string","null"],"maxLength":10000}}}}}},"responses":{"200":{"description":"Triage a safety case.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"organizationId":{"type":["string","null"]},"reporterUserId":{"type":["string","null"]},"subjectUserId":{"type":["string","null"]},"targetType":{"type":"string","enum":["user","content","organization","payment","guardian_relationship","platform"]},"targetId":{"type":["string","null"]},"subjectKey":{"type":"string"},"targetSnapshot":{"type":"object","properties":{"label":{"type":["string","null"]},"secondaryLabel":{"type":["string","null"]},"publicReference":{"type":["string","null"]}}},"category":{"type":"string","enum":["inappropriate_content","harassment_abuse","fraud","privacy","intellectual_property","account_access","child_adolescent_safety","guardian_relationship","other"]},"sensitivity":{"type":"string","enum":["standard","minor_restricted"]},"severity":{"type":"string","enum":["low","medium","high","critical"]},"status":{"type":"string","enum":["open","triaged","actioned","closed","escalated"]},"assignedToUserId":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"closedAt":{"type":["string","null"],"format":"date-time"},"reporterNarrative":{"type":["string","null"]},"internalNotes":{"type":["string","null"]},"resolutionCode":{"type":["string","null"]},"authorityReference":{"type":["string","null"]},"events":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"actorUserId":{"type":["string","null"]},"type":{"type":"string","enum":["created","assigned","status_changed","category_changed","severity_changed","notes_updated","escalated","resolved","closed"]},"details":{"type":"object","additionalProperties":{"type":["string","null"]}},"createdAt":{"type":"string","format":"date-time"}},"required":["id","actorUserId","type","details","createdAt"]}}},"required":["id","organizationId","reporterUserId","subjectUserId","targetType","targetId","subjectKey","targetSnapshot","category","sensitivity","severity","status","assignedToUserId","createdAt","updatedAt","closedAt","reporterNarrative","internalNotes","resolutionCode","authorityReference","events"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/minors/children/assurance":{"post":{"tags":["Minor accounts"],"operationId":"beginChildSponsorship","summary":"Begin a sponsored child account","description":"Starts the configured age and guardian assurance handoff. Trusted age results are never accepted in this request and raw provider evidence is never returned.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"childName":{"type":"string","minLength":1,"maxLength":100},"childEmail":{"type":"string","format":"email"},"relationship":{"type":"string","enum":["parent","legal_guardian","authorized_adult"]}},"required":["childName","childEmail","relationship"]}}}},"responses":{"200":{"description":"Begin a sponsored child account.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"redirectUrl":{"type":"string","format":"uri"}},"required":["redirectUrl"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/minors/guardian-links":{"get":{"tags":["Minor accounts"],"operationId":"listGuardianLinks","summary":"List scoped guardian relationships","parameters":[{"name":"childUserId","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"List scoped guardian relationships.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"childUserId":{"type":"string"},"guardianUserId":{"type":"string"},"relationship":{"type":"string","enum":["parent","legal_guardian","authorized_adult"]},"status":{"type":"string","enum":["pending","active","revoked","expired"]},"isPrimary":{"type":"boolean"},"authorizedAt":{"type":["string","null"],"format":"date-time"},"verifiedAt":{"type":["string","null"],"format":"date-time"},"revokedAt":{"type":["string","null"],"format":"date-time"},"expiredAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","childUserId","guardianUserId","relationship","status","isPrimary","authorizedAt","verifiedAt","revokedAt","expiredAt","createdAt"]}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/minors/guardian-links/{id}":{"delete":{"tags":["Minor accounts"],"operationId":"revokeGuardianLink","summary":"Revoke a guardian relationship","parameters":[{"name":"id","in":"path","required":true,"description":"Guardian relationship id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Revoke a guardian relationship.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"revoked":{"type":"boolean","const":true}},"required":["revoked"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/minors/guardian-links/{id}/dispute":{"post":{"tags":["Minor accounts"],"operationId":"disputeGuardianLink","summary":"Dispute a guardian relationship","parameters":[{"name":"id","in":"path","required":true,"description":"Guardian relationship id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Dispute a guardian relationship.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"safetyCaseId":{"type":"string"}},"required":["safetyCaseId"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/minors/children/{childId}/primary-guardian":{"post":{"tags":["Minor accounts"],"operationId":"transferPrimaryGuardian","summary":"Transfer primary guardianship","parameters":[{"name":"childId","in":"path","required":true,"description":"Child user id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"guardianLinkId":{"type":"string"}},"required":["guardianLinkId"]}}}},"responses":{"200":{"description":"Transfer primary guardianship.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"transferred":{"type":"boolean","const":true}},"required":["transferred"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/minors/children/{childId}/usage-limit":{"put":{"tags":["Minor accounts"],"operationId":"setMinorUsageLimit","summary":"Set a child's daily learning-time limit","parameters":[{"name":"childId","in":"path","required":true,"description":"Child user id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"limitMinutes":{"type":["integer","null"],"minimum":1,"maximum":1440},"timeZone":{"type":"string","minLength":1,"maxLength":100}},"required":["limitMinutes","timeZone"]}}}},"responses":{"200":{"description":"Set a child's daily learning-time limit.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"updated":{"type":"boolean","const":true}},"required":["updated"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/minors/children/{childId}/usage":{"get":{"tags":["Minor accounts"],"operationId":"getMinorUsage","summary":"Get bounded daily learning-time summaries","parameters":[{"name":"childId","in":"path","required":true,"description":"Child user id.","schema":{"type":"string"}},{"name":"from","in":"query","required":true,"schema":{"type":"string","format":"date"}},{"name":"to","in":"query","required":true,"schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Get bounded daily learning-time summaries.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","properties":{"usageDate":{"type":"string","format":"date"},"timeZone":{"type":"string"},"activeSeconds":{"type":"integer"},"limitMinutes":{"type":["integer","null"]},"blockedAt":{"type":["string","null"],"format":"date-time"}},"required":["usageDate","timeZone","activeSeconds","limitMinutes","blockedAt"]}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/minors/adulthood-transition":{"post":{"tags":["Minor accounts"],"operationId":"completeAdulthoodTransition","summary":"Complete an assured transition to adulthood","responses":{"200":{"description":"Complete an assured transition to adulthood.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"transitioned":{"type":"boolean","const":true}},"required":["transitioned"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/minor-safety/cases":{"post":{"tags":["Minor safety"],"operationId":"createMinorSafetyCase","summary":"Create a child-safety case","description":"Creates a child-safety case scoped to the caller's visible child or organization context.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":["string","null"]},"subjectChildUserId":{"type":["string","null"]},"targetType":{"type":["string","null"],"enum":["content","offer","organization","account","relationship"]},"targetId":{"type":["string","null"]},"category":{"type":"string","enum":["safety","privacy","age_error","guardian_relationship","content"]},"severity":{"type":"string","enum":["low","medium","high","critical"]}},"required":["category","severity"]}}}},"responses":{"201":{"description":"Create a child-safety case.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"get":{"tags":["Minor safety"],"operationId":"listMinorSafetyCases","summary":"List scoped child-safety cases","description":"Lists child-safety cases visible to the caller, optionally filtered by child and status.","parameters":[{"name":"childUserId","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string","enum":["open","triaged","actioned","closed","escalated"]}},{"name":"cursorCreatedAt","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"cursorId","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"default":50,"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"List scoped child-safety cases.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"organizationId":{"type":["string","null"]},"reporterUserId":{"type":["string","null"]},"subjectChildUserId":{"type":["string","null"]},"targetType":{"type":["string","null"],"enum":["content","offer","organization","account","relationship"]},"targetId":{"type":["string","null"]},"category":{"type":"string","enum":["safety","privacy","age_error","guardian_relationship","content"]},"severity":{"type":"string","enum":["low","medium","high","critical"]},"status":{"type":"string","enum":["open","triaged","actioned","closed","escalated"]},"assignedToUserId":{"type":["string","null"]},"resolutionCode":{"type":["string","null"]},"authorityReference":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"closedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","organizationId","reporterUserId","subjectChildUserId","targetType","targetId","category","severity","status","assignedToUserId","resolutionCode","authorityReference","createdAt","updatedAt","closedAt"]}},"nextCursor":{"type":["object","null"],"properties":{"createdAt":{"type":"string","format":"date-time"},"id":{"type":"string"}},"required":["createdAt","id"]}},"required":["items","nextCursor"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/minor-safety/cases/{id}":{"patch":{"tags":["Minor safety"],"operationId":"updateMinorSafetyCase","summary":"Triage or resolve a child-safety case","description":"Updates triage and resolution fields for a child-safety case visible to the caller.","parameters":[{"name":"id","in":"path","required":true,"description":"Safety case id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["open","triaged","actioned","closed","escalated"]},"assignedToUserId":{"type":["string","null"]},"resolutionCode":{"type":["string","null"],"maxLength":100},"authorityReference":{"type":["string","null"],"maxLength":500}},"required":["status"]}}}},"responses":{"200":{"description":"Triage or resolve a child-safety case.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"organizationId":{"type":["string","null"]},"reporterUserId":{"type":["string","null"]},"subjectChildUserId":{"type":["string","null"]},"targetType":{"type":["string","null"],"enum":["content","offer","organization","account","relationship"]},"targetId":{"type":["string","null"]},"category":{"type":"string","enum":["safety","privacy","age_error","guardian_relationship","content"]},"severity":{"type":"string","enum":["low","medium","high","critical"]},"status":{"type":"string","enum":["open","triaged","actioned","closed","escalated"]},"assignedToUserId":{"type":["string","null"]},"resolutionCode":{"type":["string","null"]},"authorityReference":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"closedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","organizationId","reporterUserId","subjectChildUserId","targetType","targetId","category","severity","status","assignedToUserId","resolutionCode","authorityReference","createdAt","updatedAt","closedAt"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/organization/minor-access":{"get":{"tags":["Organization"],"operationId":"getMinorOrganizationSettings","summary":"Get organization minor-access settings","responses":{"200":{"description":"Get organization minor-access settings.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"enabled":{"type":"boolean"},"safetyContactEmail":{"type":["string","null"],"format":"email"},"policyReviewedAt":{"type":["string","null"],"format":"date-time"}},"required":["enabled","safetyContactEmail","policyReviewedAt"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"tags":["Organization"],"operationId":"updateMinorOrganizationSettings","summary":"Update organization minor-access settings","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean"},"safetyContactEmail":{"type":["string","null"],"format":"email"},"policyReviewed":{"type":"boolean"}},"required":["enabled","safetyContactEmail","policyReviewed"]}}}},"responses":{"200":{"description":"Update organization minor-access settings.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"enabled":{"type":"boolean"},"safetyContactEmail":{"type":["string","null"],"format":"email"},"policyReviewedAt":{"type":["string","null"],"format":"date-time"}},"required":["enabled","safetyContactEmail","policyReviewedAt"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/offers/{id}/minor-review":{"put":{"tags":["Offers"],"operationId":"reviewOfferForMinors","summary":"Review an offer for minor access","parameters":[{"name":"id","in":"path","required":true,"description":"Offer id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"eligible":{"type":"boolean"},"minimumAgeBand":{"type":["string","null"],"enum":["under_12","12_15","16_17"]}},"required":["eligible"]}}}},"responses":{"200":{"description":"Review an offer for minor access.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"eligible":{"type":"boolean"},"minimumAgeBand":{"type":["string","null"],"enum":["under_12","12_15","16_17"]},"reviewedBy":{"type":["string","null"]},"reviewedAt":{"type":["string","null"],"format":"date-time"},"reviewVersion":{"type":["string","null"]}},"required":["eligible","minimumAgeBand","reviewedBy","reviewedAt","reviewVersion"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/organization/seller-profile":{"get":{"tags":["Organization"],"operationId":"getSellerProfile","summary":"Get the legal seller profile","description":"Returns the legal identity and consumer-support details published to buyers. A paid offer cannot sell until every required field is complete.","responses":{"200":{"description":"Get the legal seller profile.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"legalName":{"type":["string","null"]},"taxIdType":{"type":["string","null"],"enum":["br_cpf","br_cnpj","us_ein","us_individual","eu_vat","national"]},"taxId":{"type":["string","null"]},"address":{"type":["object","null"],"properties":{"line1":{"type":"string","minLength":1,"maxLength":200},"line2":{"type":"string","maxLength":200},"city":{"type":"string","minLength":1,"maxLength":200},"region":{"type":"string","minLength":1,"maxLength":200},"postalCode":{"type":"string","minLength":1,"maxLength":32},"country":{"type":"string","pattern":"^[A-Z]{2}$"}},"required":["line1","city","region","postalCode","country"]},"supportEmail":{"type":["string","null"],"format":"email"},"supportUrl":{"type":["string","null"]},"supportPhone":{"type":["string","null"]},"reviewedAt":{"type":["string","null"],"format":"date-time"},"ready":{"type":"boolean"}},"required":["legalName","taxIdType","taxId","address","supportEmail","supportUrl","supportPhone","reviewedAt","ready"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"put":{"tags":["Organization"],"operationId":"updateSellerProfile","summary":"Update the legal seller profile","description":"Stores the school's country-aware legal seller identity. Public identifiers are disclosed before checkout and snapshotted on each purchase; US EIN remains private and individual SSN/ITIN verification stays with Stripe.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"legalName":{"type":"string","minLength":1,"maxLength":200},"taxIdType":{"type":"string","enum":["br_cpf","br_cnpj","us_ein","us_individual","eu_vat","national"]},"taxId":{"type":["string","null"],"minLength":4,"maxLength":40},"address":{"type":"object","properties":{"line1":{"type":"string","minLength":1,"maxLength":200},"line2":{"type":"string","maxLength":200},"city":{"type":"string","minLength":1,"maxLength":200},"region":{"type":"string","minLength":1,"maxLength":200},"postalCode":{"type":"string","minLength":1,"maxLength":32},"country":{"type":"string","pattern":"^[A-Z]{2}$"}},"required":["line1","city","region","postalCode","country"]},"supportEmail":{"type":"string","format":"email"},"supportUrl":{"type":["string","null"],"format":"uri"},"supportPhone":{"type":["string","null"],"maxLength":30}},"required":["legalName","taxIdType","taxId","address","supportEmail"]}}}},"responses":{"200":{"description":"Update the legal seller profile.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"legalName":{"type":["string","null"]},"taxIdType":{"type":["string","null"],"enum":["br_cpf","br_cnpj","us_ein","us_individual","eu_vat","national"]},"taxId":{"type":["string","null"]},"address":{"type":["object","null"],"properties":{"line1":{"type":"string","minLength":1,"maxLength":200},"line2":{"type":"string","maxLength":200},"city":{"type":"string","minLength":1,"maxLength":200},"region":{"type":"string","minLength":1,"maxLength":200},"postalCode":{"type":"string","minLength":1,"maxLength":32},"country":{"type":"string","pattern":"^[A-Z]{2}$"}},"required":["line1","city","region","postalCode","country"]},"supportEmail":{"type":["string","null"],"format":"email"},"supportUrl":{"type":["string","null"]},"supportPhone":{"type":["string","null"]},"reviewedAt":{"type":["string","null"],"format":"date-time"},"ready":{"type":"boolean"}},"required":["legalName","taxIdType","taxId","address","supportEmail","supportUrl","supportPhone","reviewedAt","ready"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/members":{"get":{"tags":["Organization"],"operationId":"listMembers","summary":"List staff members","description":"The org's staff directory — every member with their org-level role. List-only: inviting or removing members happens in the dashboard (membership is managed by the auth layer, not this API).","responses":{"200":{"description":"List staff members.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","properties":{"userId":{"type":"string"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"role":{"type":"string","enum":["owner","admin","member"]}},"required":["userId","name","email","role"]}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/organization/shape":{"get":{"tags":["Organization"],"operationId":"getOrganizationShape","summary":"Get the organization's shape","description":"Live signals describing what KIND of organization this is — how many members, teams and courses it has, whether payments are connected, and whether it is still a solo operation. Everything is derived from current data, never stored, so it cannot go stale. Useful as a cheap first call to orient yourself before deciding what to suggest or do: a solo org with no payments connected needs very different help from a ten-person business.","responses":{"200":{"description":"Get the organization's shape.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"memberCount":{"type":"integer","description":"Staff members (not learners)."},"pendingInvites":{"type":"integer","description":"Outstanding, unexpired invitations."},"teamCount":{"type":"integer"},"contentCount":{"type":"integer","description":"Every content in the organization, published or not."},"paymentsConnected":{"type":"boolean","description":"A payout account is connected — selling is possible."},"solo":{"type":"boolean","description":"One member and nobody invited. The dashboard hides team machinery behind this; it is inferred, never a setting."}},"required":["memberCount","pendingInvites","teamCount","contentCount","paymentsConnected","solo"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/resolve":{"get":{"tags":["Organization"],"operationId":"resolveReference","summary":"Resolve a human reference to an id","description":"Given a human name, slug, or email, get the id that other tools need — CALL THIS FIRST, before any tool that takes an id you do not already have. It replaces brute-forcing the list endpoints: one call searches the organization's content (title + slug), learners and staff members (name + email), teams, tags, and offers, and returns a flat ranked list of candidates with exact and prefix matches first.\n\nScoped to the caller's organization; it never reaches across orgs. Results are a disambiguation aid, not full records — take the `id` and call the resource's own GET for detail. When several candidates come back and the choice is not obvious, ask the user which one they meant rather than guessing; when nothing comes back, the thing does not exist under that name — do not invent an id.\n\n`type` narrows the search to a single kind, which is both faster and less ambiguous when you already know what you are looking for (e.g. `type=team` for \"the Backend team\"). Note that `cohort` is searched ONLY when you pass `type=cohort`: cohorts live per offered root, so they cost a bounded scan of the organization's recent content and may miss cohorts on older ones — fall back to `listContentCohorts` for an exhaustive list.","parameters":[{"name":"q","in":"query","required":true,"description":"The human reference to look up: a content title or slug, a person's name or email, a team/tag/offer/cohort name. Matching is case-insensitive and partial.","schema":{"type":"string","minLength":1}},{"name":"type","in":"query","description":"Restrict to one kind of resource. Omit to search every kind except `cohort`.","schema":{"type":"string","enum":["content","learner","member","team","cohort","offer"]}},{"name":"limit","in":"query","description":"Maximum candidates to return. Keep it small — this is for disambiguation.","schema":{"default":10,"type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"description":"Resolve a human reference to an id.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"matches":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["content","learner","member","team","cohort","offer"],"description":"Which resource this id belongs to."},"id":{"type":"string","description":"The id to hand to other tools. For `learner` and `member` this is the USER id (`userId`) — the value enrollment, cohort, and ownership tools expect."},"label":{"type":"string","description":"The human name that matched — content title, person's name, etc."},"sublabel":{"description":"Short disambiguating context: an email, a slug, or the parent content.","type":["string","null"]},"href":{"description":"Dashboard path a human can open to see this record. Null when there is no page.","type":["string","null"]}},"required":["type","id","label","sublabel","href"]},"description":"Best candidates first: exact matches, then prefix matches, then substring matches. Empty when nothing in the org matches."},"query":{"type":"string","description":"The trimmed `q` that was searched, echoed back."},"truncated":{"type":"boolean","description":"True when matches were dropped before you saw them — either more candidates matched than `limit` allowed, or one kind of resource alone had more than `limit` matches and was trimmed to make room for the others. Refine `q`, or pass `type` to spend the whole `limit` on the one kind you actually want."}},"required":["matches","query","truncated"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/organization/custom-domain":{"get":{"tags":["Organization"],"operationId":"getCustomDomain","summary":"Get the custom domain","description":"The org's custom-domain status. While unverified, `dns` lists the records to add at your DNS provider. The {slug}.cursare.com subdomain keeps working either way.","responses":{"200":{"description":"Get the custom domain.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"domain":{"description":"The connected custom domain, or null when none is set.","type":["string","null"]},"verified":{"type":"boolean","description":"Whether the ownership TXT record has been verified."},"dns":{"type":["object","null"],"properties":{"cnameHost":{"type":"string","description":"The CNAME record name — the custom domain itself."},"cnameTarget":{"type":"string","description":"The CNAME record value — where the domain must point."},"txtHost":{"type":"string","description":"The ownership TXT record name (_cursare-verify.<domain>)."},"txtValue":{"type":"string","description":"The exact TXT record value proving ownership."},"ttl":{"type":"string","description":"Recommended TTL in seconds — keep it low so verification isn't stuck behind stale DNS caches."}},"required":["cnameHost","cnameTarget","txtHost","txtValue","ttl"],"description":"The DNS records still to add — present while unverified, null otherwise."}},"required":["domain","verified","dns"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"put":{"tags":["Organization"],"operationId":"setCustomDomain","summary":"Set the custom domain","description":"Connect (or replace) the org's custom domain. The domain is normalized and validated — platform subdomains and domains already connected to another organization are rejected. Returns the CNAME and ownership TXT records to add (use the suggested TTL), then call verify. Connecting a custom domain never removes the org's cursare.com subdomain.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"domain":{"type":"string","description":"The domain to connect, e.g. courses.example.com."}},"required":["domain"]}}}},"responses":{"200":{"description":"Set the custom domain.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"domain":{"description":"The connected custom domain, or null when none is set.","type":["string","null"]},"verified":{"type":"boolean","description":"Whether the ownership TXT record has been verified."},"dns":{"type":["object","null"],"properties":{"cnameHost":{"type":"string","description":"The CNAME record name — the custom domain itself."},"cnameTarget":{"type":"string","description":"The CNAME record value — where the domain must point."},"txtHost":{"type":"string","description":"The ownership TXT record name (_cursare-verify.<domain>)."},"txtValue":{"type":"string","description":"The exact TXT record value proving ownership."},"ttl":{"type":"string","description":"Recommended TTL in seconds — keep it low so verification isn't stuck behind stale DNS caches."}},"required":["cnameHost","cnameTarget","txtHost","txtValue","ttl"],"description":"The DNS records still to add — present while unverified, null otherwise."}},"required":["domain","verified","dns"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"tags":["Organization"],"operationId":"deleteCustomDomain","summary":"Disconnect the custom domain","description":"Removes the custom domain entirely. Learners keep reaching the org at its {slug}.cursare.com subdomain.","responses":{"200":{"description":"Disconnect the custom domain.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"deleted":{"type":"boolean","const":true}},"required":["deleted"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/organization/custom-domain/verify":{"post":{"tags":["Organization"],"operationId":"verifyCustomDomain","summary":"Verify the custom domain","description":"Performs a live DNS lookup of the _cursare-verify TXT record (counts against the write rate limit). On a match the domain is marked verified and registered for TLS + routing. On a mismatch this returns 400 — DNS records can take a few minutes (up to the record's TTL) to propagate, so retry later.","responses":{"200":{"description":"Verify the custom domain.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"verified":{"type":"boolean","const":true}},"required":["verified"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/media/images":{"post":{"tags":["Media"],"operationId":"uploadImage","summary":"Upload an image","description":"Uploads an image through the same organization storage, security validation, optimization, and deduplication pipeline used by the course editor. Send raw file bytes as canonical base64, without a data URL prefix. The returned permanent URL can be placed in a content cover or image block.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"filename":{"type":"string","minLength":1,"maxLength":255,"description":"Original filename, including its extension, for audit and storage metadata."},"contentType":{"type":"string","enum":["image/jpeg","image/png","image/webp","image/gif"],"description":"MIME type of the encoded image. It must match the file signature."},"data":{"type":"string","minLength":4,"maxLength":4194304,"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","description":"Raw image bytes encoded as canonical base64, without `data:image/...;base64,`. Maximum decoded size: 3 MB."}},"required":["filename","contentType","data"]}}}},"responses":{"200":{"description":"Upload an image.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"url":{"type":"string","description":"Permanent public URL stored by the organization."},"mime":{"type":"string","description":"Stored MIME type after image optimization."},"size":{"type":"integer","minimum":0,"description":"Stored byte size after image optimization."},"deduplicated":{"type":"boolean","description":"Whether identical image bytes already existed for this organization."}},"required":["url","mime","size","deduplicated"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/contents":{"get":{"tags":["Contents"],"operationId":"listContents","summary":"List contents","description":"Every content in the org, drafts included — filterable and paginated.","parameters":[{"name":"q","in":"query","description":"Substring match on title or route segment (case-insensitive).","schema":{"type":"string"}},{"name":"isPublished","in":"query","description":"Filter by whether a published document exists.","schema":{"type":"string","enum":["true","false"]}},{"name":"hasUnpublishedChanges","in":"query","description":"Filter independently by pending document changes.","schema":{"type":"string","enum":["true","false"]}},{"name":"tag","in":"query","description":"Only contents carrying this tag (exact name).","schema":{"type":"string"}},{"name":"page","in":"query","schema":{"default":1,"type":"integer","minimum":1}},{"name":"pageSize","in":"query","schema":{"default":25,"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"List contents.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"contents":{"type":"array","items":{"$ref":"#/components/schemas/Content"}},"page":{"type":"integer"},"pageSize":{"type":"integer"},"total":{"type":"integer","description":"Total matches across all pages."}},"required":["contents","page","pageSize","total"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"tags":["Contents"],"operationId":"createContent","summary":"Create a draft content","description":"Creates one unpublished learning content or profile article with an organization-unique route segment and no offer. Every document may interleave learning blocks and references. Optional tags are applied after creation; a validation failure removes the draft. Create an offer separately when the content should be enrollable or sellable.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":"string","minLength":1,"maxLength":120,"pattern":"^[a-z0-9-]+$"},"teamId":{"type":"string","minLength":1},"kind":{"type":"string","enum":["learning","article"]},"title":{"type":"string","minLength":1,"maxLength":200},"tags":{"type":"array","items":{"type":"string"},"description":"Initial tag list (names must exist in the tag registry)."}}}}}},"responses":{"201":{"description":"Create a draft content.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Content"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/contents/{id}":{"get":{"tags":["Contents"],"operationId":"getContent","summary":"Get a content","parameters":[{"name":"id","in":"path","required":true,"description":"The content id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Get a content.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Content"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"tags":["Contents"],"operationId":"updateContent","summary":"Update content settings","description":"Updates editorial settings only: discovery metadata, tags, content and certificate themes, slug, and ownership. Commercial, entry, capacity, and delivery terms belong to offer resources. Discovery metadata, tags, themes, route segment and ownership apply to every content. Title and description live inside the document header and are edited in the composer and read back via `GET /contents/{id}`.","parameters":[{"name":"id","in":"path","required":true,"description":"The content id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"tags":{"type":"array","items":{"type":"string"}},"featured":{"type":"boolean"},"seoTitle":{"type":["string","null"]},"seoDescription":{"type":["string","null"]},"noindex":{"type":"boolean"},"slug":{"type":"string","minLength":1,"maxLength":120,"pattern":"^[a-z0-9-]+$"},"theme":{"anyOf":[{"anyOf":[{"type":"string","enum":["ember","ocean","forest","orchid","graphite"]},{"type":"string","pattern":"^custom:#[0-9a-f]{6}$"}]},{"type":"null"}]},"certificateTheme":{"type":"string","enum":["classic","modern","editorial","minimal"]},"owner":{"anyOf":[{"type":"object","properties":{"teamId":{"type":"string","minLength":1}},"required":["teamId"]},{"type":"object","properties":{"userId":{"type":"string","minLength":1}},"required":["userId"]}]}}}}}},"responses":{"200":{"description":"Update content settings.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Content"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"tags":["Contents"],"operationId":"deleteContent","summary":"Delete a content","description":"Deletion is refused if the content is referenced by another or purchased.","parameters":[{"name":"id","in":"path","required":true,"description":"The content id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Delete a content.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"deleted":{"type":"boolean","const":true}},"required":["id","deleted"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/contents/{id}/publish":{"post":{"tags":["Contents"],"operationId":"publishContent","summary":"Publish the current draft","description":"Atomically validates the draft, derives its ordered published manifest, and writes both the learner document and manifest. Every reference must target published content in the same organization; self-references and cycles are refused.","parameters":[{"name":"id","in":"path","required":true,"description":"The content id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Publish the current draft.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Content"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/contents/{id}/duplicate":{"post":{"tags":["Contents"],"operationId":"duplicateContent","summary":"Duplicate a content","description":"Creates a fresh unpublished copy with a collision-safe route segment. It copies the document and editorial settings, but never offers, learners, cohorts, reviews, purchases, sales history, or the published snapshot.","parameters":[{"name":"id","in":"path","required":true,"description":"The content id to copy.","schema":{"type":"string"}}],"responses":{"201":{"description":"Duplicate a content.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Content"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/contents/{id}/learner":{"get":{"tags":["Learner delivery"],"operationId":"getLearnerContent","summary":"Get learner-safe published content","description":"Returns the full published Composer document in the shape consumed by Cursare learner components. The response is derived from the published snapshot and strips author-only quiz answer keys. Call this endpoint from a trusted server; never expose an organization API key in browser code.","parameters":[{"name":"id","in":"path","required":true,"description":"The content id to load from the credential's organization.","schema":{"type":"string"}}],"responses":{"200":{"description":"Get learner-safe published content.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The content id requested by the integration."},"routeSegment":{"type":"string","description":"The stable route segment inside the organization."},"title":{"type":"string","description":"The title from the published document header."},"description":{"description":"The description from the published document header, or null when empty.","type":["string","null"]},"coverImage":{"description":"The published cover image URL, or null when the content has no cover.","type":["string","null"]},"theme":{"description":"The content theme understood by Cursare learner components.","type":["string","null"]},"publishedAt":{"format":"date-time","description":"When this document version was published.","type":["string","null"]},"document":{"description":"The full published document after learner sanitization.","$ref":"#/$defs/LearnerDocument"}},"required":["id","routeSegment","title","description","coverImage","theme","publishedAt","document"],"description":"Published content ready to render with the Cursare learner component registry.","$defs":{"LearnerContent":{"type":"object","properties":{"id":{"type":"string","description":"The content id requested by the integration."},"routeSegment":{"type":"string","description":"The stable route segment inside the organization."},"title":{"type":"string","description":"The title from the published document header."},"description":{"description":"The description from the published document header, or null when empty.","type":["string","null"]},"coverImage":{"description":"The published cover image URL, or null when the content has no cover.","type":["string","null"]},"theme":{"description":"The content theme understood by Cursare learner components.","type":["string","null"]},"publishedAt":{"format":"date-time","description":"When this document version was published.","type":["string","null"]},"document":{"description":"The full published document after learner sanitization.","$ref":"#/$defs/LearnerDocument"}},"required":["id","routeSegment","title","description","coverImage","theme","publishedAt","document"],"description":"Published content ready to render with the Cursare learner component registry."},"__schema0":{"type":"object","properties":{"type":{"type":"string","description":"The Composer node type."},"attrs":{"description":"Learner-safe node attributes. Quiz answer keys are never included.","type":"object","additionalProperties":{}},"content":{"description":"Nested learner-safe Composer nodes.","type":"array","items":{"$ref":"#/$defs/__schema0"}},"text":{"description":"Text carried by a text node.","type":"string"},"marks":{"description":"Formatting marks on a text node.","type":"array","items":{"type":"object","properties":{"type":{"type":"string","description":"The Composer mark type."},"attrs":{"description":"Mark-specific attributes, when present.","type":"object","additionalProperties":{}}},"required":["type"]}}},"required":["type"]},"LearnerDocument":{"type":"object","properties":{"type":{"type":"string","const":"doc","description":"The root Composer document node."},"attrs":{"description":"Document-level learner-safe attributes, when present.","type":"object","additionalProperties":{}},"content":{"description":"The published learning content.","type":"array","items":{"$ref":"#/$defs/__schema0"}},"text":{"description":"Text carried directly by the document, when present.","type":"string"},"marks":{"description":"Document-level marks, when present.","type":"array","items":{"type":"object","properties":{"type":{"type":"string","description":"The Composer mark type."},"attrs":{"description":"Mark-specific attributes, when present.","type":"object","additionalProperties":{}}},"required":["type"]}}},"required":["type"],"description":"A published Composer document sanitized for learner delivery. Author-only answer keys are removed."}}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/learner-runtime/sessions":{"post":{"tags":["Learner runtime"],"operationId":"createLearnerRuntimeSession","summary":"Create a learner runtime session","description":"Exchanges a trusted organization credential for a short-lived browser token after verifying the learner's current access. Call this endpoint from a trusted server only.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"userId":{"type":"string","minLength":1,"description":"The enrolled learner's user id."},"rootContentId":{"type":"string","minLength":1,"description":"The enrolled root course id."},"origin":{"type":"string","minLength":1,"description":"The browser origin allowed to use the learner token, such as https://app.example.com."}},"required":["userId","rootContentId","origin"]}}}},"responses":{"200":{"description":"Create a learner runtime session.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"token":{"type":"string","description":"A short-lived learner runtime Bearer token."},"tokenType":{"type":"string","const":"Bearer"},"expiresAt":{"type":"string","format":"date-time"},"origin":{"type":"string","description":"The normalized browser origin bound to the token."}},"required":["token","tokenType","expiresAt","origin"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/learner-runtime/{rootContentId}":{"get":{"tags":["Learner runtime"],"operationId":"getLearnerRuntimeCourse","summary":"Get an enrolled course node and progress","description":"Uses a learner runtime token. Returns learner-safe published content plus the canonical course graph, release state, completion progress, and estimated duration.","security":[{"learnerToken":[]}],"parameters":[{"name":"rootContentId","in":"path","required":true,"description":"The root course id bound to the learner token.","schema":{"type":"string"}},{"name":"contentId","in":"query","description":"A referenced content id in the enrolled graph. Defaults to the root course.","schema":{"type":"string"}}],"responses":{"200":{"description":"Get an enrolled course node and progress.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"content":{"$ref":"#/$defs/LearnerContent"},"progress":{"$ref":"#/$defs/LearnerRuntimeProgress"}},"required":["content","progress"],"$defs":{"LearnerContent":{"type":"object","properties":{"id":{"type":"string","description":"The content id requested by the integration."},"routeSegment":{"type":"string","description":"The stable route segment inside the organization."},"title":{"type":"string","description":"The title from the published document header."},"description":{"description":"The description from the published document header, or null when empty.","type":["string","null"]},"coverImage":{"description":"The published cover image URL, or null when the content has no cover.","type":["string","null"]},"theme":{"description":"The content theme understood by Cursare learner components.","type":["string","null"]},"publishedAt":{"format":"date-time","description":"When this document version was published.","type":["string","null"]},"document":{"description":"The full published document after learner sanitization.","$ref":"#/$defs/LearnerDocument"}},"required":["id","routeSegment","title","description","coverImage","theme","publishedAt","document"],"description":"Published content ready to render with the Cursare learner component registry."},"__schema0":{"type":"object","properties":{"type":{"type":"string","description":"The Composer node type."},"attrs":{"description":"Learner-safe node attributes. Quiz answer keys are never included.","type":"object","additionalProperties":{}},"content":{"description":"Nested learner-safe Composer nodes.","type":"array","items":{"$ref":"#/$defs/__schema0"}},"text":{"description":"Text carried by a text node.","type":"string"},"marks":{"description":"Formatting marks on a text node.","type":"array","items":{"type":"object","properties":{"type":{"type":"string","description":"The Composer mark type."},"attrs":{"description":"Mark-specific attributes, when present.","type":"object","additionalProperties":{}}},"required":["type"]}}},"required":["type"]},"LearnerDocument":{"type":"object","properties":{"type":{"type":"string","const":"doc","description":"The root Composer document node."},"attrs":{"description":"Document-level learner-safe attributes, when present.","type":"object","additionalProperties":{}},"content":{"description":"The published learning content.","type":"array","items":{"$ref":"#/$defs/__schema0"}},"text":{"description":"Text carried directly by the document, when present.","type":"string"},"marks":{"description":"Document-level marks, when present.","type":"array","items":{"type":"object","properties":{"type":{"type":"string","description":"The Composer mark type."},"attrs":{"description":"Mark-specific attributes, when present.","type":"object","additionalProperties":{}}},"required":["type"]}}},"required":["type"],"description":"A published Composer document sanitized for learner delivery. Author-only answer keys are removed."},"LearnerRuntimeProgress":{"type":"object","properties":{"steps":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["section","reference"]},"id":{"type":"string"},"title":{"type":"string"},"done":{"type":"boolean"},"available":{"type":"boolean"},"current":{"type":"boolean"},"locked":{"type":"boolean"},"lockReason":{"type":["string","null"]},"unlockAt":{"type":["number","null"]},"sectionIndex":{"type":["integer","null"]},"targetContentId":{"type":["string","null"]},"routeSegment":{"type":["string","null"]}},"required":["kind","id","title","done","available","current","locked","lockReason","unlockAt","sectionIndex","targetContentId","routeSegment"]}},"rootSteps":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["section","reference"]},"id":{"type":"string"},"title":{"type":"string"},"done":{"type":"boolean"},"available":{"type":"boolean"},"current":{"type":"boolean"},"locked":{"type":"boolean"},"lockReason":{"type":["string","null"]},"unlockAt":{"type":["number","null"]},"sectionIndex":{"type":["integer","null"]},"targetContentId":{"type":["string","null"]},"routeSegment":{"type":["string","null"]}},"required":["kind","id","title","done","available","current","locked","lockReason","unlockAt","sectionIndex","targetContentId","routeSegment"]}},"courseMap":{"$ref":"#/$defs/__schema1"},"reviewHints":{"type":"array","items":{"type":"object","properties":{"targetContentId":{"type":"string"},"routeSegment":{"type":"string"},"title":{"type":"string"},"score":{"type":"integer"},"total":{"type":"integer"}},"required":["targetContentId","routeSegment","title","score","total"]}},"currentIndex":{"type":"integer"},"completed":{"type":"boolean"},"rootCompleted":{"type":"boolean"},"completedAt":{"type":["string","null"],"format":"date-time"},"estimatedSeconds":{"type":"integer","minimum":0},"justCompleted":{"type":"boolean"}},"required":["steps","rootSteps","courseMap","currentIndex","completed","rootCompleted","completedAt"],"description":"The learner's current release and completion state for an enrolled course graph."},"__schema1":{"type":"object","properties":{"key":{"type":"string"},"kind":{"type":"string","enum":["root","content","section"]},"id":{"type":"string"},"targetContentId":{"type":"string"},"title":{"type":"string"},"done":{"type":"boolean"},"available":{"type":"boolean"},"locked":{"type":"boolean"},"routeSegment":{"type":["string","null"]},"children":{"type":"array","items":{"$ref":"#/$defs/__schema1"}}},"required":["key","kind","id","targetContentId","title","done","available","locked","routeSegment","children"]}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/learner-runtime/{rootContentId}/progress":{"patch":{"tags":["Learner runtime"],"operationId":"updateLearnerRuntimeProgress","summary":"Update learner section progress","description":"Uses a learner runtime token and applies the course's canonical release and completion rules.","security":[{"learnerToken":[]}],"parameters":[{"name":"rootContentId","in":"path","required":true,"description":"The root course id bound to the learner token.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contentId":{"type":"string","minLength":1,"description":"The content node containing the section."},"sectionId":{"type":"string","minLength":1,"description":"The stable section id to update."},"done":{"type":"boolean","description":"Whether the learner completed the section."}},"required":["contentId","sectionId","done"]}}}},"responses":{"200":{"description":"Update learner section progress.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"steps":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["section","reference"]},"id":{"type":"string"},"title":{"type":"string"},"done":{"type":"boolean"},"available":{"type":"boolean"},"current":{"type":"boolean"},"locked":{"type":"boolean"},"lockReason":{"type":["string","null"]},"unlockAt":{"type":["number","null"]},"sectionIndex":{"type":["integer","null"]},"targetContentId":{"type":["string","null"]},"routeSegment":{"type":["string","null"]}},"required":["kind","id","title","done","available","current","locked","lockReason","unlockAt","sectionIndex","targetContentId","routeSegment"]}},"rootSteps":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["section","reference"]},"id":{"type":"string"},"title":{"type":"string"},"done":{"type":"boolean"},"available":{"type":"boolean"},"current":{"type":"boolean"},"locked":{"type":"boolean"},"lockReason":{"type":["string","null"]},"unlockAt":{"type":["number","null"]},"sectionIndex":{"type":["integer","null"]},"targetContentId":{"type":["string","null"]},"routeSegment":{"type":["string","null"]}},"required":["kind","id","title","done","available","current","locked","lockReason","unlockAt","sectionIndex","targetContentId","routeSegment"]}},"courseMap":{"$ref":"#/$defs/__schema0"},"reviewHints":{"type":"array","items":{"type":"object","properties":{"targetContentId":{"type":"string"},"routeSegment":{"type":"string"},"title":{"type":"string"},"score":{"type":"integer"},"total":{"type":"integer"}},"required":["targetContentId","routeSegment","title","score","total"]}},"currentIndex":{"type":"integer"},"completed":{"type":"boolean"},"rootCompleted":{"type":"boolean"},"completedAt":{"type":["string","null"],"format":"date-time"},"estimatedSeconds":{"type":"integer","minimum":0},"justCompleted":{"type":"boolean"}},"required":["steps","rootSteps","courseMap","currentIndex","completed","rootCompleted","completedAt"],"description":"The learner's current release and completion state for an enrolled course graph.","$defs":{"LearnerRuntimeProgress":{"type":"object","properties":{"steps":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["section","reference"]},"id":{"type":"string"},"title":{"type":"string"},"done":{"type":"boolean"},"available":{"type":"boolean"},"current":{"type":"boolean"},"locked":{"type":"boolean"},"lockReason":{"type":["string","null"]},"unlockAt":{"type":["number","null"]},"sectionIndex":{"type":["integer","null"]},"targetContentId":{"type":["string","null"]},"routeSegment":{"type":["string","null"]}},"required":["kind","id","title","done","available","current","locked","lockReason","unlockAt","sectionIndex","targetContentId","routeSegment"]}},"rootSteps":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["section","reference"]},"id":{"type":"string"},"title":{"type":"string"},"done":{"type":"boolean"},"available":{"type":"boolean"},"current":{"type":"boolean"},"locked":{"type":"boolean"},"lockReason":{"type":["string","null"]},"unlockAt":{"type":["number","null"]},"sectionIndex":{"type":["integer","null"]},"targetContentId":{"type":["string","null"]},"routeSegment":{"type":["string","null"]}},"required":["kind","id","title","done","available","current","locked","lockReason","unlockAt","sectionIndex","targetContentId","routeSegment"]}},"courseMap":{"$ref":"#/$defs/__schema0"},"reviewHints":{"type":"array","items":{"type":"object","properties":{"targetContentId":{"type":"string"},"routeSegment":{"type":"string"},"title":{"type":"string"},"score":{"type":"integer"},"total":{"type":"integer"}},"required":["targetContentId","routeSegment","title","score","total"]}},"currentIndex":{"type":"integer"},"completed":{"type":"boolean"},"rootCompleted":{"type":"boolean"},"completedAt":{"type":["string","null"],"format":"date-time"},"estimatedSeconds":{"type":"integer","minimum":0},"justCompleted":{"type":"boolean"}},"required":["steps","rootSteps","courseMap","currentIndex","completed","rootCompleted","completedAt"],"description":"The learner's current release and completion state for an enrolled course graph."},"__schema0":{"type":"object","properties":{"key":{"type":"string"},"kind":{"type":"string","enum":["root","content","section"]},"id":{"type":"string"},"targetContentId":{"type":"string"},"title":{"type":"string"},"done":{"type":"boolean"},"available":{"type":"boolean"},"locked":{"type":"boolean"},"routeSegment":{"type":["string","null"]},"children":{"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["key","kind","id","targetContentId","title","done","available","locked","routeSegment","children"]}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/learner-runtime/{rootContentId}/attempts":{"post":{"tags":["Learner runtime"],"operationId":"recordLearnerRuntimeAttempt","summary":"Record a learner quiz attempt","description":"Uses a learner runtime token and accepts quiz content only from the enrolled course graph.","security":[{"learnerToken":[]}],"parameters":[{"name":"rootContentId","in":"path","required":true,"description":"The root course id bound to the learner token.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contentId":{"type":"string","minLength":1,"description":"The content node containing the quiz."},"answers":{"type":"object","additionalProperties":{"type":"string"},"description":"Quiz activity ids mapped to selected option ids."}},"required":["contentId","answers"]}}}},"responses":{"200":{"description":"Record a learner quiz attempt.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"questionId":{"type":"string"},"correct":{"type":"boolean"},"correctOptionId":{"type":["string","null"]}},"required":["questionId","correct","correctOptionId"]}},"score":{"type":"integer","minimum":0},"total":{"type":"integer","exclusiveMinimum":0},"recorded":{"type":"boolean","const":true}},"required":["results","score","total","recorded"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/learner-runtime/{rootContentId}/certificate":{"get":{"tags":["Learner runtime"],"operationId":"getLearnerRuntimeCertificate","summary":"Get the learner certificate credential","description":"Uses a learner runtime token and returns a credential only after the root course is complete.","security":[{"learnerToken":[]}],"parameters":[{"name":"rootContentId","in":"path","required":true,"description":"The root course id bound to the learner token.","schema":{"type":"string"}}],"responses":{"200":{"description":"Get the learner certificate credential.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"completedAt":{"type":["string","null"],"format":"date-time"},"theme":{"type":"string","enum":["classic","modern","editorial","minimal"]}},"required":["id","completedAt","theme"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/document-schema":{"get":{"tags":["Contents"],"operationId":"getDocumentSchema","summary":"Get the document authoring guide","description":"The shared JSON schema, stable learner identifiers, composition guidance, limits and complete valid documents. MCP clients must call `get_document_schema` before `replace_content_document` or `replace_content_block`.","responses":{"200":{"description":"Get the document authoring guide.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"version":{"type":"integer","description":"Guide format version."},"dialect":{"type":"string","const":"cursare-json-v2","description":"The canonical document format."},"overview":{"type":"string","description":"How the canonical JSON document is structured."},"documentSchema":{"type":"object","additionalProperties":{},"description":"JSON Schema for the document."},"documentRules":{"type":"object","properties":{"structure":{"type":"string"},"canonicalization":{"type":"array","items":{"type":"string"}},"limits":{"type":"object","additionalProperties":{"type":"number"}},"ids":{"type":"string"}},"required":["structure","canonicalization","limits","ids"]},"compositionGuidelines":{"type":"array","items":{"type":"string"},"description":"Pedagogical, structural and accessibility guidance for a well-composed lesson."},"minimalDocument":{"description":"A complete minimal valid document to start from.","type":"object","properties":{"type":{"type":"string","const":"doc"},"attrs":{"type":"object","properties":{"version":{"type":"number","const":2}},"required":["version"]},"content":{"minItems":4,"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs","content"]},"completeDocument":{"description":"A complete, well-composed lesson demonstrating the recommended structure.","type":"object","properties":{"type":{"type":"string","const":"doc"},"attrs":{"type":"object","properties":{"version":{"type":"number","const":2}},"required":["version"]},"content":{"minItems":4,"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs","content"]}},"required":["version","dialect","overview","documentSchema","documentRules","compositionGuidelines","minimalDocument","completeDocument"],"description":"The machine-readable authoring reference for structured Cursare JSON documents.","$defs":{"__schema0":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"doc"},"attrs":{"type":"object","properties":{"version":{"type":"number","const":2}},"required":["version"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"text"},"attrs":{"type":"object","properties":{}},"text":{"type":"string","minLength":1},"marks":{"maxItems":8,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"bold"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"italic"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"strike"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"code"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"underline"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"highlight"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"link"},"attrs":{"type":"object","properties":{"href":{"type":"string","maxLength":4096},"title":{"type":["string","null"],"maxLength":500,"default":null},"download":{"default":false,"type":"boolean"}},"required":["href","title","download"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"glossary"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"definition":{"default":"","type":"string","maxLength":6000}},"required":["id","definition"]}},"required":["type"]}]}}},"required":["type","text"]},{"type":"object","properties":{"type":{"type":"string","const":"title"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"description"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"cover"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider","assetId","mimeType","width","height","size"],"default":null},"attribution":{"type":["object","null"],"properties":{"creatorName":{"type":"string","maxLength":500},"creatorUrl":{"type":"string","maxLength":4096},"sourceUrl":{"type":"string","maxLength":4096}},"required":["creatorName","creatorUrl","sourceUrl"],"default":null},"focalPoint":{"type":["object","null"],"properties":{"x":{"type":"number","minimum":0,"maximum":1},"y":{"type":"number","minimum":0,"maximum":1}},"required":["x","y"],"default":null}},"required":["id","resource","attribution","focalPoint"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"paragraph"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"heading"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"level":{"default":2,"type":"integer","minimum":1,"maximum":6},"showInConversations":{"default":true,"type":"boolean"},"requires":{"maxItems":500,"type":["array","null"],"items":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"default":null},"afterHours":{"type":["integer","null"],"minimum":0,"default":null},"dripAnchor":{"default":"enroll","type":"string","enum":["enroll","prev"]}},"required":["id","level","showInConversations","requires","afterHours","dripAnchor"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"hardBreak"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}},"marks":{"maxItems":8,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"bold"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"italic"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"strike"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"code"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"underline"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"highlight"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"link"},"attrs":{"type":"object","properties":{"href":{"type":"string","maxLength":4096},"title":{"type":["string","null"],"maxLength":500,"default":null},"download":{"default":false,"type":"boolean"}},"required":["href","title","download"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"glossary"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"definition":{"default":"","type":"string","maxLength":6000}},"required":["id","definition"]}},"required":["type"]}]}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"blockquote"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"bulletList"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"orderedList"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"order":{"default":1,"type":"integer","exclusiveMinimum":0}},"required":["id","order"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"listItem"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"horizontalRule"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"blockTitle"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"blockDescription"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"mediaSource"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"alternativeText"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"callout"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"variant":{"default":"info","type":"string","enum":["info","success","warning","danger"]}},"required":["id","variant"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"codeBlock"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"language":{"type":["string","null"],"maxLength":64,"default":null}},"required":["id","language"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"filename"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"codeSource"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tableBlock"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"table"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tableRow"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tableCell"},"attrs":{"type":"object","properties":{"colspan":{"default":1,"type":"integer","minimum":1,"maximum":1000},"rowspan":{"default":1,"type":"integer","minimum":1,"maximum":1000},"colwidth":{"maxItems":1000,"type":["array","null"],"items":{"type":"number","minimum":0},"default":null},"alignment":{"default":"left","type":"string","enum":["left","center","right"]}},"required":["colspan","rowspan","colwidth","alignment"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tableHeader"},"attrs":{"type":"object","properties":{"colspan":{"default":1,"type":"integer","minimum":1,"maximum":1000},"rowspan":{"default":1,"type":"integer","minimum":1,"maximum":1000},"colwidth":{"maxItems":1000,"type":["array","null"],"items":{"type":"number","minimum":0},"default":null},"alignment":{"default":"left","type":"string","enum":["left","center","right"]}},"required":["colspan","rowspan","colwidth","alignment"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"image"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider","assetId","mimeType","width","height","size"],"default":null},"attribution":{"type":["object","null"],"properties":{"creatorName":{"type":"string","maxLength":500},"creatorUrl":{"type":"string","maxLength":4096},"sourceUrl":{"type":"string","maxLength":4096}},"required":["creatorName","creatorUrl","sourceUrl"],"default":null},"focalPoint":{"type":["object","null"],"properties":{"x":{"type":"number","minimum":0,"maximum":1},"y":{"type":"number","minimum":0,"maximum":1}},"required":["x","y"],"default":null}},"required":["id","resource","attribution","focalPoint"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"video"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider","assetId","mimeType","width","height","size"],"default":null},"poster":{"type":["string","null"],"maxLength":4096,"default":null},"tracks":{"default":[],"maxItems":100,"type":"array","items":{"type":"object","properties":{"src":{"type":"string","maxLength":4096},"kind":{"type":"string","enum":["subtitles","captions"]},"lang":{"type":"string","maxLength":64},"label":{"type":"string","maxLength":128},"default":{"default":false,"type":"boolean"}},"required":["src","kind","lang","label","default"]}}},"required":["id","resource","poster","tracks"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"audio"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider","assetId","mimeType","width","height","size"],"default":null}},"required":["id","resource"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"embed"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider","assetId","mimeType","width","height","size"],"default":null}},"required":["id","resource"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"fileAttachment"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider","assetId","mimeType","width","height","size"],"default":null}},"required":["id","resource"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"mathBlock"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"mathSource"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"mathInline"},"attrs":{"type":"object","properties":{"source":{"default":"","type":"string","maxLength":10000}},"required":["source"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}},"marks":{"maxItems":8,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"bold"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"italic"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"strike"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"code"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"underline"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"highlight"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"link"},"attrs":{"type":"object","properties":{"href":{"type":"string","maxLength":4096},"title":{"type":["string","null"],"maxLength":500,"default":null},"download":{"default":false,"type":"boolean"}},"required":["href","title","download"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"glossary"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"definition":{"default":"","type":"string","maxLength":6000}},"required":["id","definition"]}},"required":["type"]}]}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"steps"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"step"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"quiz"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"reveal":{"default":1,"type":"integer","exclusiveMinimum":0}},"required":["id","reveal"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"question"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"correctOptionId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null}},"required":["id","correctOptionId"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"prompt"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"option"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"poll"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"openResponse"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"automatedEvaluation":{"default":true,"type":"boolean"}},"required":["id","automatedEvaluation"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"referenceAnswer"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"criterion"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"reference"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"targetContentId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"routeSegment":{"default":"","type":"string","maxLength":240},"requires":{"maxItems":500,"type":["array","null"],"items":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"default":null},"afterHours":{"type":["integer","null"],"minimum":0,"default":null},"dripAnchor":{"default":"enroll","type":"string","enum":["enroll","prev"]}},"required":["id","targetContentId","routeSegment","requires","afterHours","dripAnchor"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]}]}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/contents/{id}/document":{"get":{"tags":["Contents"],"operationId":"getContentDocument","summary":"Get the content document","description":"The editable Cursare JSON draft plus the published document learners currently read. The draft includes grading keys such as quiz `correctOptionId`s and stable learner state ids for polls, quizzes, headings and references, so treat this payload as org-staff only: never proxy it to learners or embed it in learner-facing pages.","parameters":[{"name":"id","in":"path","required":true,"description":"The content id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Get the content document.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"draftRevision":{"type":"integer","minimum":0,"description":"The current acknowledged draft revision. Full-document writes advance it; internal editor step transport is not a public API."},"draftDocument":{"description":"The editable draft document. Includes grading keys — org-staff only.","type":"object","properties":{"type":{"type":"string","const":"doc"},"attrs":{"type":"object","properties":{"version":{"type":"number","const":2}},"required":["version"]},"content":{"minItems":4,"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs","content"]},"publishedDocument":{"description":"The document learners currently read. Null means it has never been published.","type":["object","null"],"properties":{"type":{"type":"string","const":"doc"},"attrs":{"type":"object","properties":{"version":{"type":"number","const":2}},"required":["version"]},"content":{"minItems":4,"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs","content"]},"publishedAt":{"type":["string","null"],"format":"date-time","description":"When the published document was last written. Null means never published."}},"required":["draftRevision","draftDocument","publishedDocument","publishedAt"],"$defs":{"__schema0":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"doc"},"attrs":{"type":"object","properties":{"version":{"type":"number","const":2}},"required":["version"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"text"},"attrs":{"type":"object","properties":{}},"text":{"type":"string","minLength":1},"marks":{"maxItems":8,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"bold"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"italic"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"strike"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"code"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"underline"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"highlight"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"link"},"attrs":{"type":"object","properties":{"href":{"type":"string","maxLength":4096},"title":{"type":["string","null"],"maxLength":500,"default":null},"download":{"default":false,"type":"boolean"}},"required":["href","title","download"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"glossary"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"definition":{"default":"","type":"string","maxLength":6000}},"required":["id","definition"]}},"required":["type"]}]}}},"required":["type","text"]},{"type":"object","properties":{"type":{"type":"string","const":"title"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"description"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"cover"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider","assetId","mimeType","width","height","size"],"default":null},"attribution":{"type":["object","null"],"properties":{"creatorName":{"type":"string","maxLength":500},"creatorUrl":{"type":"string","maxLength":4096},"sourceUrl":{"type":"string","maxLength":4096}},"required":["creatorName","creatorUrl","sourceUrl"],"default":null},"focalPoint":{"type":["object","null"],"properties":{"x":{"type":"number","minimum":0,"maximum":1},"y":{"type":"number","minimum":0,"maximum":1}},"required":["x","y"],"default":null}},"required":["id","resource","attribution","focalPoint"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"paragraph"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"heading"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"level":{"default":2,"type":"integer","minimum":1,"maximum":6},"showInConversations":{"default":true,"type":"boolean"},"requires":{"maxItems":500,"type":["array","null"],"items":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"default":null},"afterHours":{"type":["integer","null"],"minimum":0,"default":null},"dripAnchor":{"default":"enroll","type":"string","enum":["enroll","prev"]}},"required":["id","level","showInConversations","requires","afterHours","dripAnchor"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"hardBreak"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}},"marks":{"maxItems":8,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"bold"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"italic"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"strike"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"code"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"underline"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"highlight"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"link"},"attrs":{"type":"object","properties":{"href":{"type":"string","maxLength":4096},"title":{"type":["string","null"],"maxLength":500,"default":null},"download":{"default":false,"type":"boolean"}},"required":["href","title","download"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"glossary"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"definition":{"default":"","type":"string","maxLength":6000}},"required":["id","definition"]}},"required":["type"]}]}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"blockquote"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"bulletList"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"orderedList"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"order":{"default":1,"type":"integer","exclusiveMinimum":0}},"required":["id","order"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"listItem"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"horizontalRule"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"blockTitle"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"blockDescription"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"mediaSource"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"alternativeText"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"callout"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"variant":{"default":"info","type":"string","enum":["info","success","warning","danger"]}},"required":["id","variant"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"codeBlock"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"language":{"type":["string","null"],"maxLength":64,"default":null}},"required":["id","language"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"filename"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"codeSource"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tableBlock"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"table"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tableRow"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tableCell"},"attrs":{"type":"object","properties":{"colspan":{"default":1,"type":"integer","minimum":1,"maximum":1000},"rowspan":{"default":1,"type":"integer","minimum":1,"maximum":1000},"colwidth":{"maxItems":1000,"type":["array","null"],"items":{"type":"number","minimum":0},"default":null},"alignment":{"default":"left","type":"string","enum":["left","center","right"]}},"required":["colspan","rowspan","colwidth","alignment"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tableHeader"},"attrs":{"type":"object","properties":{"colspan":{"default":1,"type":"integer","minimum":1,"maximum":1000},"rowspan":{"default":1,"type":"integer","minimum":1,"maximum":1000},"colwidth":{"maxItems":1000,"type":["array","null"],"items":{"type":"number","minimum":0},"default":null},"alignment":{"default":"left","type":"string","enum":["left","center","right"]}},"required":["colspan","rowspan","colwidth","alignment"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"image"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider","assetId","mimeType","width","height","size"],"default":null},"attribution":{"type":["object","null"],"properties":{"creatorName":{"type":"string","maxLength":500},"creatorUrl":{"type":"string","maxLength":4096},"sourceUrl":{"type":"string","maxLength":4096}},"required":["creatorName","creatorUrl","sourceUrl"],"default":null},"focalPoint":{"type":["object","null"],"properties":{"x":{"type":"number","minimum":0,"maximum":1},"y":{"type":"number","minimum":0,"maximum":1}},"required":["x","y"],"default":null}},"required":["id","resource","attribution","focalPoint"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"video"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider","assetId","mimeType","width","height","size"],"default":null},"poster":{"type":["string","null"],"maxLength":4096,"default":null},"tracks":{"default":[],"maxItems":100,"type":"array","items":{"type":"object","properties":{"src":{"type":"string","maxLength":4096},"kind":{"type":"string","enum":["subtitles","captions"]},"lang":{"type":"string","maxLength":64},"label":{"type":"string","maxLength":128},"default":{"default":false,"type":"boolean"}},"required":["src","kind","lang","label","default"]}}},"required":["id","resource","poster","tracks"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"audio"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider","assetId","mimeType","width","height","size"],"default":null}},"required":["id","resource"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"embed"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider","assetId","mimeType","width","height","size"],"default":null}},"required":["id","resource"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"fileAttachment"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider","assetId","mimeType","width","height","size"],"default":null}},"required":["id","resource"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"mathBlock"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"mathSource"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"mathInline"},"attrs":{"type":"object","properties":{"source":{"default":"","type":"string","maxLength":10000}},"required":["source"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}},"marks":{"maxItems":8,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"bold"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"italic"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"strike"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"code"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"underline"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"highlight"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"link"},"attrs":{"type":"object","properties":{"href":{"type":"string","maxLength":4096},"title":{"type":["string","null"],"maxLength":500,"default":null},"download":{"default":false,"type":"boolean"}},"required":["href","title","download"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"glossary"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"definition":{"default":"","type":"string","maxLength":6000}},"required":["id","definition"]}},"required":["type"]}]}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"steps"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"step"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"quiz"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"reveal":{"default":1,"type":"integer","exclusiveMinimum":0}},"required":["id","reveal"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"question"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"correctOptionId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null}},"required":["id","correctOptionId"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"prompt"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"option"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"poll"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"openResponse"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"automatedEvaluation":{"default":true,"type":"boolean"}},"required":["id","automatedEvaluation"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"referenceAnswer"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"criterion"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"reference"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"targetContentId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"routeSegment":{"default":"","type":"string","maxLength":240},"requires":{"maxItems":500,"type":["array","null"],"items":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"default":null},"afterHours":{"type":["integer","null"],"minimum":0,"default":null},"dripAnchor":{"default":"enroll","type":"string","enum":["enroll","prev"]}},"required":["id","targetContentId","routeSegment","requires","afterHours","dripAnchor"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]}]}}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"put":{"tags":["Contents"],"operationId":"replaceContentDocument","summary":"Replace the draft document","description":"Replaces the ENTIRE draft with a native version 2 JSON document (max 2 MB); learners see nothing until publish. MCP clients must call `get_document_schema` for the shared schema and composition guidance. The root is a doc node with attrs.version 2. Its content starts with the cover, title and description nodes, followed by ordered typed blocks and recursive references. PRESERVE BEHAVIORAL IDS when editing: headings, references, polls and quiz ids key learner answers, progress and study position — changing them can orphan that state. The returned draft includes answer keys and must not be proxied to learners.","parameters":[{"name":"id","in":"path","required":true,"description":"The content id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"document":{"description":"The full replacement Cursare JSON draft.","type":"object","properties":{"type":{"type":"string","const":"doc"},"attrs":{"type":"object","properties":{"version":{"type":"number","const":2}},"required":["version"]},"content":{"minItems":4,"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs","content"]}},"required":["document"],"$defs":{"__schema0":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"doc"},"attrs":{"type":"object","properties":{"version":{"type":"number","const":2}},"required":["version"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"text"},"attrs":{"type":"object","properties":{}},"text":{"type":"string","minLength":1},"marks":{"maxItems":8,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"bold"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"italic"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"strike"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"code"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"underline"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"highlight"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"link"},"attrs":{"type":"object","properties":{"href":{"type":"string","maxLength":4096},"title":{"type":["string","null"],"maxLength":500,"default":null},"download":{"default":false,"type":"boolean"}},"required":["href"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"glossary"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"definition":{"default":"","type":"string","maxLength":6000}},"required":["id"]}},"required":["type"]}]}}},"required":["type","text"]},{"type":"object","properties":{"type":{"type":"string","const":"title"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"description"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"cover"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider"],"default":null},"attribution":{"type":["object","null"],"properties":{"creatorName":{"type":"string","maxLength":500},"creatorUrl":{"type":"string","maxLength":4096},"sourceUrl":{"type":"string","maxLength":4096}},"required":["creatorName","creatorUrl","sourceUrl"],"default":null},"focalPoint":{"type":["object","null"],"properties":{"x":{"type":"number","minimum":0,"maximum":1},"y":{"type":"number","minimum":0,"maximum":1}},"required":["x","y"],"default":null}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"paragraph"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"heading"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"level":{"default":2,"type":"integer","minimum":1,"maximum":6},"showInConversations":{"default":true,"type":"boolean"},"requires":{"maxItems":500,"type":["array","null"],"items":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"default":null},"afterHours":{"type":["integer","null"],"minimum":0,"default":null},"dripAnchor":{"default":"enroll","type":"string","enum":["enroll","prev"]}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"hardBreak"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}},"marks":{"maxItems":8,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"bold"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"italic"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"strike"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"code"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"underline"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"highlight"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"link"},"attrs":{"type":"object","properties":{"href":{"type":"string","maxLength":4096},"title":{"type":["string","null"],"maxLength":500,"default":null},"download":{"default":false,"type":"boolean"}},"required":["href"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"glossary"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"definition":{"default":"","type":"string","maxLength":6000}},"required":["id"]}},"required":["type"]}]}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"blockquote"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"bulletList"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"orderedList"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"order":{"default":1,"type":"integer","exclusiveMinimum":0}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"listItem"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"horizontalRule"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"blockTitle"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"blockDescription"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"mediaSource"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"alternativeText"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"callout"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"variant":{"default":"info","type":"string","enum":["info","success","warning","danger"]}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"codeBlock"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"language":{"type":["string","null"],"maxLength":64,"default":null}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"filename"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"codeSource"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tableBlock"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"table"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tableRow"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tableCell"},"attrs":{"type":"object","properties":{"colspan":{"default":1,"type":"integer","minimum":1,"maximum":1000},"rowspan":{"default":1,"type":"integer","minimum":1,"maximum":1000},"colwidth":{"maxItems":1000,"type":["array","null"],"items":{"type":"number","minimum":0},"default":null},"alignment":{"default":"left","type":"string","enum":["left","center","right"]}}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tableHeader"},"attrs":{"type":"object","properties":{"colspan":{"default":1,"type":"integer","minimum":1,"maximum":1000},"rowspan":{"default":1,"type":"integer","minimum":1,"maximum":1000},"colwidth":{"maxItems":1000,"type":["array","null"],"items":{"type":"number","minimum":0},"default":null},"alignment":{"default":"left","type":"string","enum":["left","center","right"]}}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"image"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider"],"default":null},"attribution":{"type":["object","null"],"properties":{"creatorName":{"type":"string","maxLength":500},"creatorUrl":{"type":"string","maxLength":4096},"sourceUrl":{"type":"string","maxLength":4096}},"required":["creatorName","creatorUrl","sourceUrl"],"default":null},"focalPoint":{"type":["object","null"],"properties":{"x":{"type":"number","minimum":0,"maximum":1},"y":{"type":"number","minimum":0,"maximum":1}},"required":["x","y"],"default":null}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"video"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider"],"default":null},"poster":{"type":["string","null"],"maxLength":4096,"default":null},"tracks":{"default":[],"maxItems":100,"type":"array","items":{"type":"object","properties":{"src":{"type":"string","maxLength":4096},"kind":{"type":"string","enum":["subtitles","captions"]},"lang":{"type":"string","maxLength":64},"label":{"type":"string","maxLength":128},"default":{"default":false,"type":"boolean"}},"required":["src","kind","lang","label"]}}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"audio"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider"],"default":null}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"embed"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider"],"default":null}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"fileAttachment"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider"],"default":null}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"mathBlock"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"mathSource"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"mathInline"},"attrs":{"type":"object","properties":{"source":{"default":"","type":"string","maxLength":10000}}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}},"marks":{"maxItems":8,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"bold"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"italic"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"strike"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"code"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"underline"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"highlight"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"link"},"attrs":{"type":"object","properties":{"href":{"type":"string","maxLength":4096},"title":{"type":["string","null"],"maxLength":500,"default":null},"download":{"default":false,"type":"boolean"}},"required":["href"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"glossary"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"definition":{"default":"","type":"string","maxLength":6000}},"required":["id"]}},"required":["type"]}]}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"steps"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"step"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"quiz"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"reveal":{"default":1,"type":"integer","exclusiveMinimum":0}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"question"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"correctOptionId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"prompt"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"option"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"poll"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"openResponse"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"automatedEvaluation":{"default":true,"type":"boolean"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"referenceAnswer"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"criterion"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"reference"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"targetContentId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"routeSegment":{"default":"","type":"string","maxLength":240},"requires":{"maxItems":500,"type":["array","null"],"items":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"default":null},"afterHours":{"type":["integer","null"],"minimum":0,"default":null},"dripAnchor":{"default":"enroll","type":"string","enum":["enroll","prev"]}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]}]}}}}}},"responses":{"200":{"description":"Replace the draft document.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"draftDocument":{"description":"The editable draft document. Includes grading keys — org-staff only.","type":"object","properties":{"type":{"type":"string","const":"doc"},"attrs":{"type":"object","properties":{"version":{"type":"number","const":2}},"required":["version"]},"content":{"minItems":4,"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs","content"]},"draftRevision":{"type":"integer","minimum":0,"description":"The current acknowledged draft revision. Full-document writes advance it; internal editor step transport is not a public API."}},"required":["draftDocument","draftRevision"],"description":"The draft document and acknowledged revision after a full replacement.","$defs":{"__schema0":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"doc"},"attrs":{"type":"object","properties":{"version":{"type":"number","const":2}},"required":["version"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"text"},"attrs":{"type":"object","properties":{}},"text":{"type":"string","minLength":1},"marks":{"maxItems":8,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"bold"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"italic"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"strike"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"code"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"underline"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"highlight"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"link"},"attrs":{"type":"object","properties":{"href":{"type":"string","maxLength":4096},"title":{"type":["string","null"],"maxLength":500,"default":null},"download":{"default":false,"type":"boolean"}},"required":["href","title","download"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"glossary"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"definition":{"default":"","type":"string","maxLength":6000}},"required":["id","definition"]}},"required":["type"]}]}}},"required":["type","text"]},{"type":"object","properties":{"type":{"type":"string","const":"title"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"description"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"cover"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider","assetId","mimeType","width","height","size"],"default":null},"attribution":{"type":["object","null"],"properties":{"creatorName":{"type":"string","maxLength":500},"creatorUrl":{"type":"string","maxLength":4096},"sourceUrl":{"type":"string","maxLength":4096}},"required":["creatorName","creatorUrl","sourceUrl"],"default":null},"focalPoint":{"type":["object","null"],"properties":{"x":{"type":"number","minimum":0,"maximum":1},"y":{"type":"number","minimum":0,"maximum":1}},"required":["x","y"],"default":null}},"required":["id","resource","attribution","focalPoint"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"paragraph"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"heading"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"level":{"default":2,"type":"integer","minimum":1,"maximum":6},"showInConversations":{"default":true,"type":"boolean"},"requires":{"maxItems":500,"type":["array","null"],"items":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"default":null},"afterHours":{"type":["integer","null"],"minimum":0,"default":null},"dripAnchor":{"default":"enroll","type":"string","enum":["enroll","prev"]}},"required":["id","level","showInConversations","requires","afterHours","dripAnchor"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"hardBreak"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}},"marks":{"maxItems":8,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"bold"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"italic"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"strike"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"code"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"underline"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"highlight"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"link"},"attrs":{"type":"object","properties":{"href":{"type":"string","maxLength":4096},"title":{"type":["string","null"],"maxLength":500,"default":null},"download":{"default":false,"type":"boolean"}},"required":["href","title","download"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"glossary"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"definition":{"default":"","type":"string","maxLength":6000}},"required":["id","definition"]}},"required":["type"]}]}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"blockquote"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"bulletList"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"orderedList"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"order":{"default":1,"type":"integer","exclusiveMinimum":0}},"required":["id","order"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"listItem"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"horizontalRule"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"blockTitle"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"blockDescription"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"mediaSource"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"alternativeText"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"callout"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"variant":{"default":"info","type":"string","enum":["info","success","warning","danger"]}},"required":["id","variant"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"codeBlock"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"language":{"type":["string","null"],"maxLength":64,"default":null}},"required":["id","language"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"filename"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"codeSource"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tableBlock"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"table"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tableRow"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tableCell"},"attrs":{"type":"object","properties":{"colspan":{"default":1,"type":"integer","minimum":1,"maximum":1000},"rowspan":{"default":1,"type":"integer","minimum":1,"maximum":1000},"colwidth":{"maxItems":1000,"type":["array","null"],"items":{"type":"number","minimum":0},"default":null},"alignment":{"default":"left","type":"string","enum":["left","center","right"]}},"required":["colspan","rowspan","colwidth","alignment"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tableHeader"},"attrs":{"type":"object","properties":{"colspan":{"default":1,"type":"integer","minimum":1,"maximum":1000},"rowspan":{"default":1,"type":"integer","minimum":1,"maximum":1000},"colwidth":{"maxItems":1000,"type":["array","null"],"items":{"type":"number","minimum":0},"default":null},"alignment":{"default":"left","type":"string","enum":["left","center","right"]}},"required":["colspan","rowspan","colwidth","alignment"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"image"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider","assetId","mimeType","width","height","size"],"default":null},"attribution":{"type":["object","null"],"properties":{"creatorName":{"type":"string","maxLength":500},"creatorUrl":{"type":"string","maxLength":4096},"sourceUrl":{"type":"string","maxLength":4096}},"required":["creatorName","creatorUrl","sourceUrl"],"default":null},"focalPoint":{"type":["object","null"],"properties":{"x":{"type":"number","minimum":0,"maximum":1},"y":{"type":"number","minimum":0,"maximum":1}},"required":["x","y"],"default":null}},"required":["id","resource","attribution","focalPoint"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"video"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider","assetId","mimeType","width","height","size"],"default":null},"poster":{"type":["string","null"],"maxLength":4096,"default":null},"tracks":{"default":[],"maxItems":100,"type":"array","items":{"type":"object","properties":{"src":{"type":"string","maxLength":4096},"kind":{"type":"string","enum":["subtitles","captions"]},"lang":{"type":"string","maxLength":64},"label":{"type":"string","maxLength":128},"default":{"default":false,"type":"boolean"}},"required":["src","kind","lang","label","default"]}}},"required":["id","resource","poster","tracks"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"audio"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider","assetId","mimeType","width","height","size"],"default":null}},"required":["id","resource"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"embed"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider","assetId","mimeType","width","height","size"],"default":null}},"required":["id","resource"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"fileAttachment"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider","assetId","mimeType","width","height","size"],"default":null}},"required":["id","resource"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"mathBlock"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"mathSource"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"mathInline"},"attrs":{"type":"object","properties":{"source":{"default":"","type":"string","maxLength":10000}},"required":["source"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}},"marks":{"maxItems":8,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"bold"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"italic"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"strike"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"code"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"underline"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"highlight"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"link"},"attrs":{"type":"object","properties":{"href":{"type":"string","maxLength":4096},"title":{"type":["string","null"],"maxLength":500,"default":null},"download":{"default":false,"type":"boolean"}},"required":["href","title","download"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"glossary"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"definition":{"default":"","type":"string","maxLength":6000}},"required":["id","definition"]}},"required":["type"]}]}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"steps"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"step"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"quiz"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"reveal":{"default":1,"type":"integer","exclusiveMinimum":0}},"required":["id","reveal"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"question"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"correctOptionId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null}},"required":["id","correctOptionId"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"prompt"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"option"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"poll"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"openResponse"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"automatedEvaluation":{"default":true,"type":"boolean"}},"required":["id","automatedEvaluation"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"referenceAnswer"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"criterion"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"reference"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"targetContentId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"routeSegment":{"default":"","type":"string","maxLength":240},"requires":{"maxItems":500,"type":["array","null"],"items":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"default":null},"afterHours":{"type":["integer","null"],"minimum":0,"default":null},"dripAnchor":{"default":"enroll","type":"string","enum":["enroll","prev"]}},"required":["id","targetContentId","routeSegment","requires","afterHours","dripAnchor"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]}]}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/contents/{id}/document/blocks/{blockId}":{"patch":{"tags":["Contents"],"operationId":"replaceContentBlock","summary":"Replace one draft content block","description":"Replaces exactly one existing top-level draft block while leaving the rest of the document untouched. Call `get_content_document` first and send its current `draftRevision` as `expectedRevision`; a stale revision is rejected instead of overwriting concurrent edits. The replacement must keep the same block type and stable block id. Preserve nested behavioral ids such as quiz questions and options when editing their copy or settings. Learners see nothing until `publish_content` is called separately.","parameters":[{"name":"id","in":"path","required":true,"description":"The content id.","schema":{"type":"string"}},{"name":"blockId","in":"path","required":true,"description":"The stable id of the existing top-level block.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"expectedRevision":{"type":"integer","minimum":0,"description":"The draftRevision returned by get_content_document."},"block":{"description":"The complete replacement block. Its type and attrs.id must match the current block.","$ref":"#/$defs/__schema0"}},"required":["expectedRevision","block"],"$defs":{"__schema0":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"doc"},"attrs":{"type":"object","properties":{"version":{"type":"number","const":2}},"required":["version"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"text"},"attrs":{"type":"object","properties":{}},"text":{"type":"string","minLength":1},"marks":{"maxItems":8,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"bold"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"italic"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"strike"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"code"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"underline"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"highlight"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"link"},"attrs":{"type":"object","properties":{"href":{"type":"string","maxLength":4096},"title":{"type":["string","null"],"maxLength":500,"default":null},"download":{"default":false,"type":"boolean"}},"required":["href"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"glossary"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"definition":{"default":"","type":"string","maxLength":6000}},"required":["id"]}},"required":["type"]}]}}},"required":["type","text"]},{"type":"object","properties":{"type":{"type":"string","const":"title"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"description"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"cover"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider"],"default":null},"attribution":{"type":["object","null"],"properties":{"creatorName":{"type":"string","maxLength":500},"creatorUrl":{"type":"string","maxLength":4096},"sourceUrl":{"type":"string","maxLength":4096}},"required":["creatorName","creatorUrl","sourceUrl"],"default":null},"focalPoint":{"type":["object","null"],"properties":{"x":{"type":"number","minimum":0,"maximum":1},"y":{"type":"number","minimum":0,"maximum":1}},"required":["x","y"],"default":null}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"paragraph"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"heading"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"level":{"default":2,"type":"integer","minimum":1,"maximum":6},"showInConversations":{"default":true,"type":"boolean"},"requires":{"maxItems":500,"type":["array","null"],"items":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"default":null},"afterHours":{"type":["integer","null"],"minimum":0,"default":null},"dripAnchor":{"default":"enroll","type":"string","enum":["enroll","prev"]}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"hardBreak"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}},"marks":{"maxItems":8,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"bold"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"italic"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"strike"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"code"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"underline"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"highlight"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"link"},"attrs":{"type":"object","properties":{"href":{"type":"string","maxLength":4096},"title":{"type":["string","null"],"maxLength":500,"default":null},"download":{"default":false,"type":"boolean"}},"required":["href"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"glossary"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"definition":{"default":"","type":"string","maxLength":6000}},"required":["id"]}},"required":["type"]}]}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"blockquote"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"bulletList"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"orderedList"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"order":{"default":1,"type":"integer","exclusiveMinimum":0}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"listItem"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"horizontalRule"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"blockTitle"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"blockDescription"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"mediaSource"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"alternativeText"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"callout"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"variant":{"default":"info","type":"string","enum":["info","success","warning","danger"]}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"codeBlock"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"language":{"type":["string","null"],"maxLength":64,"default":null}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"filename"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"codeSource"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tableBlock"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"table"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tableRow"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tableCell"},"attrs":{"type":"object","properties":{"colspan":{"default":1,"type":"integer","minimum":1,"maximum":1000},"rowspan":{"default":1,"type":"integer","minimum":1,"maximum":1000},"colwidth":{"maxItems":1000,"type":["array","null"],"items":{"type":"number","minimum":0},"default":null},"alignment":{"default":"left","type":"string","enum":["left","center","right"]}}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tableHeader"},"attrs":{"type":"object","properties":{"colspan":{"default":1,"type":"integer","minimum":1,"maximum":1000},"rowspan":{"default":1,"type":"integer","minimum":1,"maximum":1000},"colwidth":{"maxItems":1000,"type":["array","null"],"items":{"type":"number","minimum":0},"default":null},"alignment":{"default":"left","type":"string","enum":["left","center","right"]}}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"image"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider"],"default":null},"attribution":{"type":["object","null"],"properties":{"creatorName":{"type":"string","maxLength":500},"creatorUrl":{"type":"string","maxLength":4096},"sourceUrl":{"type":"string","maxLength":4096}},"required":["creatorName","creatorUrl","sourceUrl"],"default":null},"focalPoint":{"type":["object","null"],"properties":{"x":{"type":"number","minimum":0,"maximum":1},"y":{"type":"number","minimum":0,"maximum":1}},"required":["x","y"],"default":null}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"video"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider"],"default":null},"poster":{"type":["string","null"],"maxLength":4096,"default":null},"tracks":{"default":[],"maxItems":100,"type":"array","items":{"type":"object","properties":{"src":{"type":"string","maxLength":4096},"kind":{"type":"string","enum":["subtitles","captions"]},"lang":{"type":"string","maxLength":64},"label":{"type":"string","maxLength":128},"default":{"default":false,"type":"boolean"}},"required":["src","kind","lang","label"]}}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"audio"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider"],"default":null}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"embed"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider"],"default":null}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"fileAttachment"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider"],"default":null}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"mathBlock"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"mathSource"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"mathInline"},"attrs":{"type":"object","properties":{"source":{"default":"","type":"string","maxLength":10000}}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}},"marks":{"maxItems":8,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"bold"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"italic"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"strike"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"code"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"underline"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"highlight"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"link"},"attrs":{"type":"object","properties":{"href":{"type":"string","maxLength":4096},"title":{"type":["string","null"],"maxLength":500,"default":null},"download":{"default":false,"type":"boolean"}},"required":["href"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"glossary"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"definition":{"default":"","type":"string","maxLength":6000}},"required":["id"]}},"required":["type"]}]}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"steps"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"step"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"quiz"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"reveal":{"default":1,"type":"integer","exclusiveMinimum":0}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"question"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"correctOptionId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"prompt"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"option"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"poll"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"openResponse"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"automatedEvaluation":{"default":true,"type":"boolean"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"referenceAnswer"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"criterion"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"reference"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"targetContentId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"routeSegment":{"default":"","type":"string","maxLength":240},"requires":{"maxItems":500,"type":["array","null"],"items":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"default":null},"afterHours":{"type":["integer","null"],"minimum":0,"default":null},"dripAnchor":{"default":"enroll","type":"string","enum":["enroll","prev"]}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]}]}}}}}},"responses":{"200":{"description":"Replace one draft content block.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"draftDocument":{"description":"The editable draft document. Includes grading keys — org-staff only.","type":"object","properties":{"type":{"type":"string","const":"doc"},"attrs":{"type":"object","properties":{"version":{"type":"number","const":2}},"required":["version"]},"content":{"minItems":4,"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs","content"]},"draftRevision":{"type":"integer","minimum":0,"description":"The current acknowledged draft revision. Full-document writes advance it; internal editor step transport is not a public API."}},"required":["draftDocument","draftRevision"],"description":"The draft document and acknowledged revision after a full replacement.","$defs":{"__schema0":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"doc"},"attrs":{"type":"object","properties":{"version":{"type":"number","const":2}},"required":["version"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"text"},"attrs":{"type":"object","properties":{}},"text":{"type":"string","minLength":1},"marks":{"maxItems":8,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"bold"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"italic"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"strike"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"code"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"underline"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"highlight"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"link"},"attrs":{"type":"object","properties":{"href":{"type":"string","maxLength":4096},"title":{"type":["string","null"],"maxLength":500,"default":null},"download":{"default":false,"type":"boolean"}},"required":["href","title","download"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"glossary"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"definition":{"default":"","type":"string","maxLength":6000}},"required":["id","definition"]}},"required":["type"]}]}}},"required":["type","text"]},{"type":"object","properties":{"type":{"type":"string","const":"title"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"description"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"cover"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider","assetId","mimeType","width","height","size"],"default":null},"attribution":{"type":["object","null"],"properties":{"creatorName":{"type":"string","maxLength":500},"creatorUrl":{"type":"string","maxLength":4096},"sourceUrl":{"type":"string","maxLength":4096}},"required":["creatorName","creatorUrl","sourceUrl"],"default":null},"focalPoint":{"type":["object","null"],"properties":{"x":{"type":"number","minimum":0,"maximum":1},"y":{"type":"number","minimum":0,"maximum":1}},"required":["x","y"],"default":null}},"required":["id","resource","attribution","focalPoint"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"paragraph"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"heading"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"level":{"default":2,"type":"integer","minimum":1,"maximum":6},"showInConversations":{"default":true,"type":"boolean"},"requires":{"maxItems":500,"type":["array","null"],"items":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"default":null},"afterHours":{"type":["integer","null"],"minimum":0,"default":null},"dripAnchor":{"default":"enroll","type":"string","enum":["enroll","prev"]}},"required":["id","level","showInConversations","requires","afterHours","dripAnchor"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"hardBreak"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}},"marks":{"maxItems":8,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"bold"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"italic"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"strike"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"code"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"underline"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"highlight"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"link"},"attrs":{"type":"object","properties":{"href":{"type":"string","maxLength":4096},"title":{"type":["string","null"],"maxLength":500,"default":null},"download":{"default":false,"type":"boolean"}},"required":["href","title","download"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"glossary"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"definition":{"default":"","type":"string","maxLength":6000}},"required":["id","definition"]}},"required":["type"]}]}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"blockquote"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"bulletList"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"orderedList"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"order":{"default":1,"type":"integer","exclusiveMinimum":0}},"required":["id","order"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"listItem"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"horizontalRule"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"blockTitle"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"blockDescription"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"mediaSource"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"alternativeText"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"callout"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"variant":{"default":"info","type":"string","enum":["info","success","warning","danger"]}},"required":["id","variant"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"codeBlock"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"language":{"type":["string","null"],"maxLength":64,"default":null}},"required":["id","language"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"filename"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"codeSource"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tableBlock"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"table"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tableRow"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tableCell"},"attrs":{"type":"object","properties":{"colspan":{"default":1,"type":"integer","minimum":1,"maximum":1000},"rowspan":{"default":1,"type":"integer","minimum":1,"maximum":1000},"colwidth":{"maxItems":1000,"type":["array","null"],"items":{"type":"number","minimum":0},"default":null},"alignment":{"default":"left","type":"string","enum":["left","center","right"]}},"required":["colspan","rowspan","colwidth","alignment"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tableHeader"},"attrs":{"type":"object","properties":{"colspan":{"default":1,"type":"integer","minimum":1,"maximum":1000},"rowspan":{"default":1,"type":"integer","minimum":1,"maximum":1000},"colwidth":{"maxItems":1000,"type":["array","null"],"items":{"type":"number","minimum":0},"default":null},"alignment":{"default":"left","type":"string","enum":["left","center","right"]}},"required":["colspan","rowspan","colwidth","alignment"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"image"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider","assetId","mimeType","width","height","size"],"default":null},"attribution":{"type":["object","null"],"properties":{"creatorName":{"type":"string","maxLength":500},"creatorUrl":{"type":"string","maxLength":4096},"sourceUrl":{"type":"string","maxLength":4096}},"required":["creatorName","creatorUrl","sourceUrl"],"default":null},"focalPoint":{"type":["object","null"],"properties":{"x":{"type":"number","minimum":0,"maximum":1},"y":{"type":"number","minimum":0,"maximum":1}},"required":["x","y"],"default":null}},"required":["id","resource","attribution","focalPoint"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"video"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider","assetId","mimeType","width","height","size"],"default":null},"poster":{"type":["string","null"],"maxLength":4096,"default":null},"tracks":{"default":[],"maxItems":100,"type":"array","items":{"type":"object","properties":{"src":{"type":"string","maxLength":4096},"kind":{"type":"string","enum":["subtitles","captions"]},"lang":{"type":"string","maxLength":64},"label":{"type":"string","maxLength":128},"default":{"default":false,"type":"boolean"}},"required":["src","kind","lang","label","default"]}}},"required":["id","resource","poster","tracks"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"audio"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider","assetId","mimeType","width","height","size"],"default":null}},"required":["id","resource"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"embed"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider","assetId","mimeType","width","height","size"],"default":null}},"required":["id","resource"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"fileAttachment"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"resource":{"type":["object","null"],"properties":{"source":{"type":"string","maxLength":4096},"url":{"type":"string","maxLength":4096},"provider":{"type":"string","maxLength":64},"assetId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"mimeType":{"type":["string","null"],"maxLength":128,"default":null},"width":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"height":{"type":["integer","null"],"exclusiveMinimum":0,"default":null},"size":{"type":["integer","null"],"minimum":0,"default":null}},"required":["source","url","provider","assetId","mimeType","width","height","size"],"default":null}},"required":["id","resource"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"mathBlock"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"mathSource"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"mathInline"},"attrs":{"type":"object","properties":{"source":{"default":"","type":"string","maxLength":10000}},"required":["source"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}},"marks":{"maxItems":8,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"bold"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"italic"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"strike"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"code"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"underline"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"highlight"},"attrs":{"type":"object","properties":{}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"link"},"attrs":{"type":"object","properties":{"href":{"type":"string","maxLength":4096},"title":{"type":["string","null"],"maxLength":500,"default":null},"download":{"default":false,"type":"boolean"}},"required":["href","title","download"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"glossary"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"definition":{"default":"","type":"string","maxLength":6000}},"required":["id","definition"]}},"required":["type"]}]}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"steps"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"step"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"quiz"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"reveal":{"default":1,"type":"integer","exclusiveMinimum":0}},"required":["id","reveal"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"question"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"correctOptionId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null}},"required":["id","correctOptionId"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"prompt"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"option"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"poll"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"openResponse"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"automatedEvaluation":{"default":true,"type":"boolean"}},"required":["id","automatedEvaluation"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"referenceAnswer"},"attrs":{"type":"object","properties":{}},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"criterion"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"}},"required":["id"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]},{"type":"object","properties":{"type":{"type":"string","const":"reference"},"attrs":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"targetContentId":{"type":["string","null"],"minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$","default":null},"routeSegment":{"default":"","type":"string","maxLength":240},"requires":{"maxItems":500,"type":["array","null"],"items":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9:_-]*$"},"default":null},"afterHours":{"type":["integer","null"],"minimum":0,"default":null},"dripAnchor":{"default":"enroll","type":"string","enum":["enroll","prev"]}},"required":["id","targetContentId","routeSegment","requires","afterHours","dripAnchor"]},"content":{"maxItems":20000,"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["type","attrs"]}]}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/offers":{"get":{"tags":["Offers"],"operationId":"listOffers","summary":"List the organization's offers","description":"Every offer across the org's courses, grouped by course (primary offer first), each with its course's slug/title/published state. Archived offers are excluded unless `includeArchived=true`.","parameters":[{"name":"includeArchived","in":"query","description":"Include archived offers.","schema":{"default":"false","type":"string","enum":["true","false"]}}],"responses":{"200":{"description":"List the organization's offers.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"contentId":{"type":"string","description":"The course this offer sells."},"name":{"type":"string"},"isPrimary":{"type":"boolean","description":"The course's canonical single-CTA offer (at most one per course)."},"status":{"type":"string","enum":["active","archived"],"description":"Archived offers stop selling but keep their sales/learners."},"price":{"type":["integer","null"],"description":"Price in the currency's minor unit (cents). Null/0 = free."},"currency":{"type":"string","description":"ISO currency code, e.g. `BRL`."},"installments":{"type":["integer","null"],"description":"Max monthly card installments (2–12). Null/1 = full price only."},"withdrawalDays":{"anyOf":[{"type":"number","const":7},{"type":"number","const":15},{"type":"number","const":21},{"type":"number","const":30}],"description":"Buyer withdrawal window in calendar days. It can extend but never shorten 7 days."},"listed":{"type":"boolean","description":"Whether this public offer shows in the organization's catalog. Free and paid offers may be listed; restricted offers are always unlisted."},"accessMode":{"type":"string","enum":["public","email_domain","private_link","email_domain_or_link"],"description":"Who may enroll or start checkout through this offer."},"allowedEmailDomains":{"type":"array","items":{"type":"string"},"description":"Verified corporate email domains accepted by domain-gated modes."},"accessLinkActive":{"type":"boolean","description":"Whether the offer currently has a non-expired private link."},"accessLinkExpiresAt":{"format":"date-time","description":"Private-link expiry, or null for no automatic expiry.","type":["string","null"]},"accessDurationDays":{"type":["integer","null"],"description":"Access duration after activation, in days. Null means indefinite access."},"affiliateCommissionBps":{"type":"integer","description":"Affiliate commission, in basis points (100 = 1%)."},"deliveryMode":{"type":"string","enum":["self_paced","cohort"],"description":"`self_paced` enrolls directly; `cohort` requires a delivery cohort."},"autoCreateCohort":{"type":"boolean","description":"Auto-open a new cohort when none is enrollable."},"cohortDurationDays":{"type":["integer","null"],"description":"Cohort length in days. Null uses the 30-day automatic-cohort default."},"cohortEnrollmentWindowDays":{"type":["integer","null"],"description":"Days after start that a new automatic cohort accepts later learners. Null = until cohort end; 0 = founding enrollment only."},"defaultCohortSeatLimit":{"type":["integer","null"],"description":"Seat cap per cohort. Null = unlimited."},"cohortTutorId":{"description":"Fixed cohort tutor. Null = round-robin over the team's cohort-role members.","type":["string","null"]},"discussionEnabled":{"type":"boolean","description":"Per-course discussion for this offer's learners."},"seatLimit":{"type":["integer","null"],"description":"Enrollment cap for this offer. Null = unlimited."},"requiresApproval":{"type":"boolean","description":"Sign-ups become requests staff review before granting access."},"intakeFormId":{"description":"A reusable intake form filled before enrolling, or null.","type":["string","null"]},"minorEligible":{"type":"boolean","description":"Whether this exact offer revision passed minor review."},"minorMinimumAgeBand":{"type":["string","null"],"enum":["under_12","12_15","16_17"]},"minorReviewedAt":{"format":"date-time","type":["string","null"]},"minorReviewVersion":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"contentSlug":{"type":"string"},"contentTitle":{"type":"string"},"contentPublished":{"type":"boolean"}},"required":["id","contentId","name","isPrimary","status","price","currency","installments","withdrawalDays","listed","accessMode","allowedEmailDomains","accessLinkActive","accessLinkExpiresAt","accessDurationDays","affiliateCommissionBps","deliveryMode","autoCreateCohort","cohortDurationDays","cohortEnrollmentWindowDays","defaultCohortSeatLimit","cohortTutorId","discussionEnabled","seatLimit","requiresApproval","intakeFormId","minorEligible","minorMinimumAgeBand","minorReviewedAt","minorReviewVersion","createdAt","updatedAt","contentSlug","contentTitle","contentPublished"]}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/contents/{id}/offers":{"get":{"tags":["Offers"],"operationId":"listContentOffers","summary":"List a content's offers","description":"The sellable offers of one course, primary first. Archived excluded unless `includeArchived=true`.","parameters":[{"name":"id","in":"path","required":true,"description":"The content id.","schema":{"type":"string"}},{"name":"includeArchived","in":"query","schema":{"default":"false","type":"string","enum":["true","false"]}}],"responses":{"200":{"description":"List a content's offers.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"contentId":{"type":"string","description":"The course this offer sells."},"name":{"type":"string"},"isPrimary":{"type":"boolean","description":"The course's canonical single-CTA offer (at most one per course)."},"status":{"type":"string","enum":["active","archived"],"description":"Archived offers stop selling but keep their sales/learners."},"price":{"type":["integer","null"],"description":"Price in the currency's minor unit (cents). Null/0 = free."},"currency":{"type":"string","description":"ISO currency code, e.g. `BRL`."},"installments":{"type":["integer","null"],"description":"Max monthly card installments (2–12). Null/1 = full price only."},"withdrawalDays":{"anyOf":[{"type":"number","const":7},{"type":"number","const":15},{"type":"number","const":21},{"type":"number","const":30}],"description":"Buyer withdrawal window in calendar days. It can extend but never shorten 7 days."},"listed":{"type":"boolean","description":"Whether this public offer shows in the organization's catalog. Free and paid offers may be listed; restricted offers are always unlisted."},"accessMode":{"type":"string","enum":["public","email_domain","private_link","email_domain_or_link"],"description":"Who may enroll or start checkout through this offer."},"allowedEmailDomains":{"type":"array","items":{"type":"string"},"description":"Verified corporate email domains accepted by domain-gated modes."},"accessLinkActive":{"type":"boolean","description":"Whether the offer currently has a non-expired private link."},"accessLinkExpiresAt":{"format":"date-time","description":"Private-link expiry, or null for no automatic expiry.","type":["string","null"]},"accessDurationDays":{"type":["integer","null"],"description":"Access duration after activation, in days. Null means indefinite access."},"affiliateCommissionBps":{"type":"integer","description":"Affiliate commission, in basis points (100 = 1%)."},"deliveryMode":{"type":"string","enum":["self_paced","cohort"],"description":"`self_paced` enrolls directly; `cohort` requires a delivery cohort."},"autoCreateCohort":{"type":"boolean","description":"Auto-open a new cohort when none is enrollable."},"cohortDurationDays":{"type":["integer","null"],"description":"Cohort length in days. Null uses the 30-day automatic-cohort default."},"cohortEnrollmentWindowDays":{"type":["integer","null"],"description":"Days after start that a new automatic cohort accepts later learners. Null = until cohort end; 0 = founding enrollment only."},"defaultCohortSeatLimit":{"type":["integer","null"],"description":"Seat cap per cohort. Null = unlimited."},"cohortTutorId":{"description":"Fixed cohort tutor. Null = round-robin over the team's cohort-role members.","type":["string","null"]},"discussionEnabled":{"type":"boolean","description":"Per-course discussion for this offer's learners."},"seatLimit":{"type":["integer","null"],"description":"Enrollment cap for this offer. Null = unlimited."},"requiresApproval":{"type":"boolean","description":"Sign-ups become requests staff review before granting access."},"intakeFormId":{"description":"A reusable intake form filled before enrolling, or null.","type":["string","null"]},"minorEligible":{"type":"boolean","description":"Whether this exact offer revision passed minor review."},"minorMinimumAgeBand":{"type":["string","null"],"enum":["under_12","12_15","16_17"]},"minorReviewedAt":{"format":"date-time","type":["string","null"]},"minorReviewVersion":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","contentId","name","isPrimary","status","price","currency","installments","withdrawalDays","listed","accessMode","allowedEmailDomains","accessLinkActive","accessLinkExpiresAt","accessDurationDays","affiliateCommissionBps","deliveryMode","autoCreateCohort","cohortDurationDays","cohortEnrollmentWindowDays","defaultCohortSeatLimit","cohortTutorId","discussionEnabled","seatLimit","requiresApproval","intakeFormId","minorEligible","minorMinimumAgeBand","minorReviewedAt","minorReviewVersion","createdAt","updatedAt"]}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"tags":["Offers"],"operationId":"createOffer","summary":"Create an offer","description":"Add a non-primary sellable offer to a course. It must share the course's currency (free and paid offers may coexist); a priced offer needs a connected payment account.","parameters":[{"name":"id","in":"path","required":true,"description":"The content id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"price":{"type":["integer","null"],"minimum":0,"maximum":100000000},"currency":{"type":"string","minLength":3,"maxLength":3},"accessDurationDays":{"type":["integer","null"],"minimum":1,"maximum":36500},"installments":{"type":["integer","null"],"minimum":2,"maximum":12},"listed":{"type":"boolean"},"withdrawalDays":{"anyOf":[{"type":"number","const":7},{"type":"number","const":15},{"type":"number","const":21},{"type":"number","const":30}]},"accessMode":{"type":"string","enum":["public","email_domain","private_link","email_domain_or_link"]},"allowedEmailDomains":{"maxItems":20,"type":"array","items":{"type":"string","minLength":3,"maxLength":253}},"seatLimit":{"type":["integer","null"],"minimum":0,"maximum":10000000},"requiresApproval":{"type":"boolean"},"deliveryMode":{"type":"string","enum":["self_paced","cohort"]},"autoCreateCohort":{"type":"boolean"},"cohortDurationDays":{"type":["integer","null"],"minimum":1,"maximum":3650},"cohortEnrollmentWindowDays":{"type":["integer","null"],"minimum":0,"maximum":3650,"description":"Days after start that a new automatic cohort accepts later learners. Null = until cohort end; 0 = founding enrollment only."},"defaultCohortSeatLimit":{"type":["integer","null"],"minimum":1,"maximum":10000000},"cohortTutorId":{"type":["string","null"],"minLength":1},"discussionEnabled":{"type":"boolean"},"intakeFormId":{"type":["string","null"],"minLength":1},"affiliateCommissionBps":{"type":"integer","minimum":0,"maximum":10000}},"required":["name","price","currency"]}}}},"responses":{"201":{"description":"Create an offer.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"contentId":{"type":"string","description":"The course this offer sells."},"name":{"type":"string"},"isPrimary":{"type":"boolean","description":"The course's canonical single-CTA offer (at most one per course)."},"status":{"type":"string","enum":["active","archived"],"description":"Archived offers stop selling but keep their sales/learners."},"price":{"type":["integer","null"],"description":"Price in the currency's minor unit (cents). Null/0 = free."},"currency":{"type":"string","description":"ISO currency code, e.g. `BRL`."},"installments":{"type":["integer","null"],"description":"Max monthly card installments (2–12). Null/1 = full price only."},"withdrawalDays":{"anyOf":[{"type":"number","const":7},{"type":"number","const":15},{"type":"number","const":21},{"type":"number","const":30}],"description":"Buyer withdrawal window in calendar days. It can extend but never shorten 7 days."},"listed":{"type":"boolean","description":"Whether this public offer shows in the organization's catalog. Free and paid offers may be listed; restricted offers are always unlisted."},"accessMode":{"type":"string","enum":["public","email_domain","private_link","email_domain_or_link"],"description":"Who may enroll or start checkout through this offer."},"allowedEmailDomains":{"type":"array","items":{"type":"string"},"description":"Verified corporate email domains accepted by domain-gated modes."},"accessLinkActive":{"type":"boolean","description":"Whether the offer currently has a non-expired private link."},"accessLinkExpiresAt":{"format":"date-time","description":"Private-link expiry, or null for no automatic expiry.","type":["string","null"]},"accessDurationDays":{"type":["integer","null"],"description":"Access duration after activation, in days. Null means indefinite access."},"affiliateCommissionBps":{"type":"integer","description":"Affiliate commission, in basis points (100 = 1%)."},"deliveryMode":{"type":"string","enum":["self_paced","cohort"],"description":"`self_paced` enrolls directly; `cohort` requires a delivery cohort."},"autoCreateCohort":{"type":"boolean","description":"Auto-open a new cohort when none is enrollable."},"cohortDurationDays":{"type":["integer","null"],"description":"Cohort length in days. Null uses the 30-day automatic-cohort default."},"cohortEnrollmentWindowDays":{"type":["integer","null"],"description":"Days after start that a new automatic cohort accepts later learners. Null = until cohort end; 0 = founding enrollment only."},"defaultCohortSeatLimit":{"type":["integer","null"],"description":"Seat cap per cohort. Null = unlimited."},"cohortTutorId":{"description":"Fixed cohort tutor. Null = round-robin over the team's cohort-role members.","type":["string","null"]},"discussionEnabled":{"type":"boolean","description":"Per-course discussion for this offer's learners."},"seatLimit":{"type":["integer","null"],"description":"Enrollment cap for this offer. Null = unlimited."},"requiresApproval":{"type":"boolean","description":"Sign-ups become requests staff review before granting access."},"intakeFormId":{"description":"A reusable intake form filled before enrolling, or null.","type":["string","null"]},"minorEligible":{"type":"boolean","description":"Whether this exact offer revision passed minor review."},"minorMinimumAgeBand":{"type":["string","null"],"enum":["under_12","12_15","16_17"]},"minorReviewedAt":{"format":"date-time","type":["string","null"]},"minorReviewVersion":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","contentId","name","isPrimary","status","price","currency","installments","withdrawalDays","listed","accessMode","allowedEmailDomains","accessLinkActive","accessLinkExpiresAt","accessDurationDays","affiliateCommissionBps","deliveryMode","autoCreateCohort","cohortDurationDays","cohortEnrollmentWindowDays","defaultCohortSeatLimit","cohortTutorId","discussionEnabled","seatLimit","requiresApproval","intakeFormId","minorEligible","minorMinimumAgeBand","minorReviewedAt","minorReviewVersion","createdAt","updatedAt"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/offers/{id}":{"get":{"tags":["Offers"],"operationId":"getOffer","summary":"Get an offer","description":"One offer with its live seat usage and enrollment counts.","parameters":[{"name":"id","in":"path","required":true,"description":"The offer id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Get an offer.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"contentId":{"type":"string","description":"The course this offer sells."},"name":{"type":"string"},"isPrimary":{"type":"boolean","description":"The course's canonical single-CTA offer (at most one per course)."},"status":{"type":"string","enum":["active","archived"],"description":"Archived offers stop selling but keep their sales/learners."},"price":{"type":["integer","null"],"description":"Price in the currency's minor unit (cents). Null/0 = free."},"currency":{"type":"string","description":"ISO currency code, e.g. `BRL`."},"installments":{"type":["integer","null"],"description":"Max monthly card installments (2–12). Null/1 = full price only."},"withdrawalDays":{"anyOf":[{"type":"number","const":7},{"type":"number","const":15},{"type":"number","const":21},{"type":"number","const":30}],"description":"Buyer withdrawal window in calendar days. It can extend but never shorten 7 days."},"listed":{"type":"boolean","description":"Whether this public offer shows in the organization's catalog. Free and paid offers may be listed; restricted offers are always unlisted."},"accessMode":{"type":"string","enum":["public","email_domain","private_link","email_domain_or_link"],"description":"Who may enroll or start checkout through this offer."},"allowedEmailDomains":{"type":"array","items":{"type":"string"},"description":"Verified corporate email domains accepted by domain-gated modes."},"accessLinkActive":{"type":"boolean","description":"Whether the offer currently has a non-expired private link."},"accessLinkExpiresAt":{"format":"date-time","description":"Private-link expiry, or null for no automatic expiry.","type":["string","null"]},"accessDurationDays":{"type":["integer","null"],"description":"Access duration after activation, in days. Null means indefinite access."},"affiliateCommissionBps":{"type":"integer","description":"Affiliate commission, in basis points (100 = 1%)."},"deliveryMode":{"type":"string","enum":["self_paced","cohort"],"description":"`self_paced` enrolls directly; `cohort` requires a delivery cohort."},"autoCreateCohort":{"type":"boolean","description":"Auto-open a new cohort when none is enrollable."},"cohortDurationDays":{"type":["integer","null"],"description":"Cohort length in days. Null uses the 30-day automatic-cohort default."},"cohortEnrollmentWindowDays":{"type":["integer","null"],"description":"Days after start that a new automatic cohort accepts later learners. Null = until cohort end; 0 = founding enrollment only."},"defaultCohortSeatLimit":{"type":["integer","null"],"description":"Seat cap per cohort. Null = unlimited."},"cohortTutorId":{"description":"Fixed cohort tutor. Null = round-robin over the team's cohort-role members.","type":["string","null"]},"discussionEnabled":{"type":"boolean","description":"Per-course discussion for this offer's learners."},"seatLimit":{"type":["integer","null"],"description":"Enrollment cap for this offer. Null = unlimited."},"requiresApproval":{"type":"boolean","description":"Sign-ups become requests staff review before granting access."},"intakeFormId":{"description":"A reusable intake form filled before enrolling, or null.","type":["string","null"]},"minorEligible":{"type":"boolean","description":"Whether this exact offer revision passed minor review."},"minorMinimumAgeBand":{"type":["string","null"],"enum":["under_12","12_15","16_17"]},"minorReviewedAt":{"format":"date-time","type":["string","null"]},"minorReviewVersion":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"seats":{"type":"object","properties":{"used":{"type":"integer","description":"Active learners enrolled through this offer."},"limit":{"type":["integer","null"]},"full":{"type":"boolean"}},"required":["used","limit","full"]},"enrollment":{"type":"object","properties":{"learners":{"type":"integer","description":"Active learners enrolled through this offer."},"pendingRequests":{"type":"integer"}},"required":["learners","pendingRequests"]}},"required":["id","contentId","name","isPrimary","status","price","currency","installments","withdrawalDays","listed","accessMode","allowedEmailDomains","accessLinkActive","accessLinkExpiresAt","accessDurationDays","affiliateCommissionBps","deliveryMode","autoCreateCohort","cohortDurationDays","cohortEnrollmentWindowDays","defaultCohortSeatLimit","cohortTutorId","discussionEnabled","seatLimit","requiresApproval","intakeFormId","minorEligible","minorMinimumAgeBand","minorReviewedAt","minorReviewVersion","createdAt","updatedAt","seats","enrollment"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"tags":["Offers"],"operationId":"updateOffer","summary":"Update an offer","description":"Patch any subset of an offer's commerce/format/enrollment fields. Currency changes must keep the course's active offers on one currency; going paid needs a payment account.","parameters":[{"name":"id","in":"path","required":true,"description":"The offer id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"price":{"type":["integer","null"],"minimum":0,"maximum":100000000},"currency":{"type":"string","minLength":3,"maxLength":3},"accessDurationDays":{"type":["integer","null"],"minimum":1,"maximum":36500},"installments":{"type":["integer","null"],"minimum":2,"maximum":12},"listed":{"type":"boolean"},"withdrawalDays":{"anyOf":[{"type":"number","const":7},{"type":"number","const":15},{"type":"number","const":21},{"type":"number","const":30}]},"accessMode":{"type":"string","enum":["public","email_domain","private_link","email_domain_or_link"]},"allowedEmailDomains":{"maxItems":20,"type":"array","items":{"type":"string","minLength":3,"maxLength":253}},"seatLimit":{"type":["integer","null"],"minimum":0,"maximum":10000000},"requiresApproval":{"type":"boolean"},"deliveryMode":{"type":"string","enum":["self_paced","cohort"]},"autoCreateCohort":{"type":"boolean"},"cohortDurationDays":{"type":["integer","null"],"minimum":1,"maximum":3650},"cohortEnrollmentWindowDays":{"type":["integer","null"],"minimum":0,"maximum":3650,"description":"Days after start that a new automatic cohort accepts later learners. Null = until cohort end; 0 = founding enrollment only."},"defaultCohortSeatLimit":{"type":["integer","null"],"minimum":1,"maximum":10000000},"cohortTutorId":{"type":["string","null"],"minLength":1},"discussionEnabled":{"type":"boolean"},"intakeFormId":{"type":["string","null"],"minLength":1},"affiliateCommissionBps":{"type":"integer","minimum":0,"maximum":10000}}}}}},"responses":{"200":{"description":"Update an offer.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"contentId":{"type":"string","description":"The course this offer sells."},"name":{"type":"string"},"isPrimary":{"type":"boolean","description":"The course's canonical single-CTA offer (at most one per course)."},"status":{"type":"string","enum":["active","archived"],"description":"Archived offers stop selling but keep their sales/learners."},"price":{"type":["integer","null"],"description":"Price in the currency's minor unit (cents). Null/0 = free."},"currency":{"type":"string","description":"ISO currency code, e.g. `BRL`."},"installments":{"type":["integer","null"],"description":"Max monthly card installments (2–12). Null/1 = full price only."},"withdrawalDays":{"anyOf":[{"type":"number","const":7},{"type":"number","const":15},{"type":"number","const":21},{"type":"number","const":30}],"description":"Buyer withdrawal window in calendar days. It can extend but never shorten 7 days."},"listed":{"type":"boolean","description":"Whether this public offer shows in the organization's catalog. Free and paid offers may be listed; restricted offers are always unlisted."},"accessMode":{"type":"string","enum":["public","email_domain","private_link","email_domain_or_link"],"description":"Who may enroll or start checkout through this offer."},"allowedEmailDomains":{"type":"array","items":{"type":"string"},"description":"Verified corporate email domains accepted by domain-gated modes."},"accessLinkActive":{"type":"boolean","description":"Whether the offer currently has a non-expired private link."},"accessLinkExpiresAt":{"format":"date-time","description":"Private-link expiry, or null for no automatic expiry.","type":["string","null"]},"accessDurationDays":{"type":["integer","null"],"description":"Access duration after activation, in days. Null means indefinite access."},"affiliateCommissionBps":{"type":"integer","description":"Affiliate commission, in basis points (100 = 1%)."},"deliveryMode":{"type":"string","enum":["self_paced","cohort"],"description":"`self_paced` enrolls directly; `cohort` requires a delivery cohort."},"autoCreateCohort":{"type":"boolean","description":"Auto-open a new cohort when none is enrollable."},"cohortDurationDays":{"type":["integer","null"],"description":"Cohort length in days. Null uses the 30-day automatic-cohort default."},"cohortEnrollmentWindowDays":{"type":["integer","null"],"description":"Days after start that a new automatic cohort accepts later learners. Null = until cohort end; 0 = founding enrollment only."},"defaultCohortSeatLimit":{"type":["integer","null"],"description":"Seat cap per cohort. Null = unlimited."},"cohortTutorId":{"description":"Fixed cohort tutor. Null = round-robin over the team's cohort-role members.","type":["string","null"]},"discussionEnabled":{"type":"boolean","description":"Per-course discussion for this offer's learners."},"seatLimit":{"type":["integer","null"],"description":"Enrollment cap for this offer. Null = unlimited."},"requiresApproval":{"type":"boolean","description":"Sign-ups become requests staff review before granting access."},"intakeFormId":{"description":"A reusable intake form filled before enrolling, or null.","type":["string","null"]},"minorEligible":{"type":"boolean","description":"Whether this exact offer revision passed minor review."},"minorMinimumAgeBand":{"type":["string","null"],"enum":["under_12","12_15","16_17"]},"minorReviewedAt":{"format":"date-time","type":["string","null"]},"minorReviewVersion":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","contentId","name","isPrimary","status","price","currency","installments","withdrawalDays","listed","accessMode","allowedEmailDomains","accessLinkActive","accessLinkExpiresAt","accessDurationDays","affiliateCommissionBps","deliveryMode","autoCreateCohort","cohortDurationDays","cohortEnrollmentWindowDays","defaultCohortSeatLimit","cohortTutorId","discussionEnabled","seatLimit","requiresApproval","intakeFormId","minorEligible","minorMinimumAgeBand","minorReviewedAt","minorReviewVersion","createdAt","updatedAt"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/offers/{id}/access-link":{"post":{"tags":["Offers"],"operationId":"rotateOfferAccessLink","summary":"Generate or rotate a private offer link","description":"Returns a new bearer secret once and immediately invalidates the previous link. The offer must use `private_link` or `email_domain_or_link` access.","parameters":[{"name":"id","in":"path","required":true,"description":"The offer id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"expiresInDays":{"default":30,"description":"Automatic expiry. Null keeps the link valid until explicitly revoked.","anyOf":[{"anyOf":[{"type":"number","const":7},{"type":"number","const":30},{"type":"number","const":90}]},{"type":"null"}]}}}}}},"responses":{"200":{"description":"Generate or rotate a private offer link.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"token":{"type":"string","description":"Bearer secret. It is returned only once and is not recoverable."},"expiresAt":{"format":"date-time","type":["string","null"]}},"required":["token","expiresAt"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"tags":["Offers"],"operationId":"revokeOfferAccessLink","summary":"Revoke a private offer link","description":"Immediately invalidates the offer's current bearer link.","parameters":[{"name":"id","in":"path","required":true,"description":"The offer id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Revoke a private offer link.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"revoked":{"type":"boolean","const":true}},"required":["id","revoked"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/offers/{id}/duplicate":{"post":{"tags":["Offers"],"operationId":"duplicateOffer","summary":"Duplicate an offer","description":"Copy reusable terms into a new active, non-primary, unlisted offer. Credentials and history are never copied.","parameters":[{"name":"id","in":"path","required":true,"description":"The offer id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"description":"Name for the copied offer.","type":"string","minLength":1,"maxLength":120}}}}}},"responses":{"201":{"description":"Duplicate an offer.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"contentId":{"type":"string","description":"The course this offer sells."},"name":{"type":"string"},"isPrimary":{"type":"boolean","description":"The course's canonical single-CTA offer (at most one per course)."},"status":{"type":"string","enum":["active","archived"],"description":"Archived offers stop selling but keep their sales/learners."},"price":{"type":["integer","null"],"description":"Price in the currency's minor unit (cents). Null/0 = free."},"currency":{"type":"string","description":"ISO currency code, e.g. `BRL`."},"installments":{"type":["integer","null"],"description":"Max monthly card installments (2–12). Null/1 = full price only."},"withdrawalDays":{"anyOf":[{"type":"number","const":7},{"type":"number","const":15},{"type":"number","const":21},{"type":"number","const":30}],"description":"Buyer withdrawal window in calendar days. It can extend but never shorten 7 days."},"listed":{"type":"boolean","description":"Whether this public offer shows in the organization's catalog. Free and paid offers may be listed; restricted offers are always unlisted."},"accessMode":{"type":"string","enum":["public","email_domain","private_link","email_domain_or_link"],"description":"Who may enroll or start checkout through this offer."},"allowedEmailDomains":{"type":"array","items":{"type":"string"},"description":"Verified corporate email domains accepted by domain-gated modes."},"accessLinkActive":{"type":"boolean","description":"Whether the offer currently has a non-expired private link."},"accessLinkExpiresAt":{"format":"date-time","description":"Private-link expiry, or null for no automatic expiry.","type":["string","null"]},"accessDurationDays":{"type":["integer","null"],"description":"Access duration after activation, in days. Null means indefinite access."},"affiliateCommissionBps":{"type":"integer","description":"Affiliate commission, in basis points (100 = 1%)."},"deliveryMode":{"type":"string","enum":["self_paced","cohort"],"description":"`self_paced` enrolls directly; `cohort` requires a delivery cohort."},"autoCreateCohort":{"type":"boolean","description":"Auto-open a new cohort when none is enrollable."},"cohortDurationDays":{"type":["integer","null"],"description":"Cohort length in days. Null uses the 30-day automatic-cohort default."},"cohortEnrollmentWindowDays":{"type":["integer","null"],"description":"Days after start that a new automatic cohort accepts later learners. Null = until cohort end; 0 = founding enrollment only."},"defaultCohortSeatLimit":{"type":["integer","null"],"description":"Seat cap per cohort. Null = unlimited."},"cohortTutorId":{"description":"Fixed cohort tutor. Null = round-robin over the team's cohort-role members.","type":["string","null"]},"discussionEnabled":{"type":"boolean","description":"Per-course discussion for this offer's learners."},"seatLimit":{"type":["integer","null"],"description":"Enrollment cap for this offer. Null = unlimited."},"requiresApproval":{"type":"boolean","description":"Sign-ups become requests staff review before granting access."},"intakeFormId":{"description":"A reusable intake form filled before enrolling, or null.","type":["string","null"]},"minorEligible":{"type":"boolean","description":"Whether this exact offer revision passed minor review."},"minorMinimumAgeBand":{"type":["string","null"],"enum":["under_12","12_15","16_17"]},"minorReviewedAt":{"format":"date-time","type":["string","null"]},"minorReviewVersion":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","contentId","name","isPrimary","status","price","currency","installments","withdrawalDays","listed","accessMode","allowedEmailDomains","accessLinkActive","accessLinkExpiresAt","accessDurationDays","affiliateCommissionBps","deliveryMode","autoCreateCohort","cohortDurationDays","cohortEnrollmentWindowDays","defaultCohortSeatLimit","cohortTutorId","discussionEnabled","seatLimit","requiresApproval","intakeFormId","minorEligible","minorMinimumAgeBand","minorReviewedAt","minorReviewVersion","createdAt","updatedAt"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/offers/{id}/set-primary":{"post":{"tags":["Offers"],"operationId":"setPrimaryOffer","summary":"Make an offer primary","description":"Promote an active offer to the course's canonical enrollment option.","parameters":[{"name":"id","in":"path","required":true,"description":"The offer id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Make an offer primary.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"isPrimary":{"type":"boolean","const":true}},"required":["id","isPrimary"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/offers/{id}/archive":{"post":{"tags":["Offers"],"operationId":"archiveOffer","summary":"Archive an offer","description":"Retire an offer (it stops selling; its sales and learners are kept). The primary offer can't be archived.","parameters":[{"name":"id","in":"path","required":true,"description":"The offer id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Archive an offer.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","const":"archived"}},"required":["id","status"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/learners":{"get":{"tags":["Learners"],"operationId":"listLearners","summary":"List all enrollments","description":"Enrollments visible to the caller, paginated. Owner/admin sees the whole organization; other members see only courses they own or whose owning team grants them `learners`.","parameters":[{"name":"q","in":"query","description":"Search by learner name/email.","schema":{"type":"string"}},{"name":"status","in":"query","description":"Filter by completion state.","schema":{"type":"string","enum":["in-progress","completed"]}},{"name":"page","in":"query","schema":{"default":1,"type":"integer","minimum":1}},{"name":"pageSize","in":"query","schema":{"default":25,"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"List all enrollments.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"learners":{"type":"array","items":{"$ref":"#/components/schemas/Learner"}},"page":{"type":"integer"},"pageSize":{"type":"integer"},"total":{"type":"integer"}},"required":["learners","page","pageSize","total"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/contents/{id}/learners":{"get":{"tags":["Learners"],"operationId":"listContentLearners","summary":"List a content's learners","description":"The content's roster with per-learner progress, enrollment status, cohort, and intake answers. Requires ownership, org owner/admin, or the `learners` role on the owning team.","parameters":[{"name":"id","in":"path","required":true,"description":"The content id.","schema":{"type":"string"}}],"responses":{"200":{"description":"List a content's learners.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","properties":{"userId":{"type":"string"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"doneSteps":{"type":"integer"},"totalSteps":{"type":"integer"},"completed":{"type":"boolean"},"lastQuiz":{"type":["object","null"],"properties":{"score":{"type":"integer"},"total":{"type":"integer"}},"required":["score","total"],"description":"The learner's most recent quiz attempt, if any."},"enrolledAt":{"type":"string","format":"date-time"},"accessStartsAt":{"type":"string","format":"date-time"},"accessEndsAt":{"type":["string","null"],"format":"date-time"},"status":{"type":"string","enum":["active","expired","refunded","past_due","suspended"],"description":"Enrollment status. Only `active` grants access; `refunded` and `past_due` keep the row for history and re-activation."},"cohortId":{"description":"The cohort (cohort) the learner belongs to on this course, if any.","type":["string","null"]},"intakeAnswers":{"type":["object","null"],"additionalProperties":{"type":"string"},"description":"Answers to the content's enrollment questions, keyed by question id. Null when the learner never filled the form (buyers skip it)."}},"required":["userId","name","email","doneSteps","totalSteps","completed","lastQuiz","enrolledAt","accessStartsAt","accessEndsAt","status","cohortId","intakeAnswers"]}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"tags":["Learners"],"operationId":"enrollLearner","summary":"Enroll a learner by email","description":"Admin grant — no purchase required; the seat cap still applies. The email must belong to an existing Cursare user. On a cohort-delivered offer the learner is bound to a dated cohort: pass `cohortId` to pick one, or omit it to follow the course's cohort policy (auto-open, or a 400 when no cohort is open).","parameters":[{"name":"id","in":"path","required":true,"description":"The content id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"cohortId":{"type":"string","description":"Delivery courses only: the dated cohort (cohort) to enroll the learner into. Ignored for self-paced offers."}},"required":["email"]}}}},"responses":{"201":{"description":"Enroll a learner by email.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"userId":{"type":"string"},"email":{"type":"string","format":"email"},"enrolledAt":{"type":"string","format":"date-time"},"accessStartsAt":{"type":"string","format":"date-time"},"accessEndsAt":{"format":"date-time","type":["string","null"]}},"required":["userId","email","enrolledAt","accessStartsAt","accessEndsAt"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/contents/{id}/learners/{userId}":{"delete":{"tags":["Learners"],"operationId":"unenrollLearner","summary":"Revoke an enrollment","description":"Revokes the root enrollment and its contextual curriculum access without deleting the learner's progress or history. Re-enrolling the learner restores access to the same root-scoped progress. Nested courses never receive separate enrollment rows.","parameters":[{"name":"id","in":"path","required":true,"description":"The content id.","schema":{"type":"string"}},{"name":"userId","in":"path","required":true,"description":"The Cursare user id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Revoke an enrollment.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"contentId":{"type":"string"},"userId":{"type":"string"},"unenrolled":{"type":"boolean","const":true}},"required":["contentId","userId","unenrolled"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"tags":["Learners"],"operationId":"updateLearner","summary":"Set a learner's internal metadata","description":"Replaces the organization's private metadata on ONE enrollment — a Stripe-style key→value bag for your own systems (CRM id, cohort, lead source, internal notes). It is REPLACE, not merge: the object you send becomes the whole bag, so send every key you want to keep (an empty object clears it). Never shown to the learner. Keys and values are strings. The response returns the resulting bag. Org-admin only (owner/admin) — metadata is not exposed on the viewer-scoped roster read.","parameters":[{"name":"id","in":"path","required":true,"description":"The content id.","schema":{"type":"string"}},{"name":"userId","in":"path","required":true,"description":"The Cursare user id of the enrolled learner.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"metadata":{"type":"object","additionalProperties":{"type":"string"}}},"required":["metadata"]}}}},"responses":{"200":{"description":"Set a learner's internal metadata.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"contentId":{"type":"string"},"userId":{"type":"string"},"metadata":{"type":"object","additionalProperties":{"type":"string"}}},"required":["contentId","userId","metadata"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/contents/{id}/learners/{userId}/reset":{"post":{"tags":["Learners"],"operationId":"resetLearnerProgress","summary":"Reset a learner's progress","description":"Restarts the course for ONE learner. DESTRUCTIVE — their progress is ERASED (every section they had completed, on the course and on its modules) and their completion is reopened; there is no undo. The enrollment SURVIVES: they keep access and their seat, and no purchase is refunded — this restarts the course, it does not remove the learner (that is `unenrollLearner`). Quiz history is kept, so mastery and insights survive. Drip re-anchors, because the per-section completion timestamps that pace it are wiped. A user id that isn't enrolled is a silent no-op. Confirm with a human before calling this. Use `resetLearnerProgressBulk` to restart several learners in one request.","parameters":[{"name":"id","in":"path","required":true,"description":"The content id.","schema":{"type":"string"}},{"name":"userId","in":"path","required":true,"description":"The Cursare user id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Reset a learner's progress.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"contentId":{"type":"string"},"userId":{"type":"string"},"reset":{"type":"boolean","const":true}},"required":["contentId","userId","reset"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/contents/{id}/learners/reset":{"post":{"tags":["Learners"],"operationId":"resetLearnerProgressBulk","summary":"Reset many learners' progress","description":"The bulk sibling of `resetLearnerProgress`: restarts the course for every listed learner in one shot. DESTRUCTIVE — each learner's progress is ERASED (every section they had completed, on the course and on its modules) and their completion is reopened; there is no undo. The enrollments SURVIVE: everyone keeps access and their seat, and no purchase is refunded — this restarts the course, it does not remove learners (that is `unenrollLearner`). Quiz history is kept, so mastery and insights survive. Drip re-anchors, because the per-section completion timestamps that pace it are wiped. Ids that aren't enrolled are silently skipped, so compare `reset` against the number you sent. Confirm with a human before calling this on a real roster.","parameters":[{"name":"id","in":"path","required":true,"description":"The content id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"userIds":{"type":"array","items":{"type":"string","minLength":1}}},"required":["userIds"]}}}},"responses":{"200":{"description":"Reset many learners' progress.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"contentId":{"type":"string"},"requested":{"type":"integer","description":"How many distinct user ids were submitted."},"reset":{"type":"integer","description":"How many enrollments were actually wiped."}},"required":["contentId","requested","reset"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/contents/{id}/learners/{userId}/mastery":{"get":{"tags":["Learners"],"operationId":"getLearnerMastery","summary":"Get a learner's mastery signal","description":"The adaptive-learning read for ONE learner on ONE course: which questions they keep missing and which modules they should revisit. Past attempts are re-graded against the CURRENT published answer key, so questions since removed simply drop out. Use it to answer 'what is this learner weak on?' and to decide what to review. Read-only, and it never exposes the answer key — you get counts per question id, not the correct options. The user must be enrolled in the content.","parameters":[{"name":"id","in":"path","required":true,"description":"The content id.","schema":{"type":"string"}},{"name":"userId","in":"path","required":true,"description":"The Cursare user id of the enrolled learner.","schema":{"type":"string"}}],"responses":{"200":{"description":"Get a learner's mastery signal.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"contentId":{"type":"string"},"userId":{"type":"string"},"lastQuiz":{"type":["object","null"],"properties":{"score":{"type":"integer"},"total":{"type":"integer"}},"required":["score","total"],"description":"The learner's most recent quiz attempt on this content, if any."},"questions":{"type":"array","items":{"type":"object","properties":{"questionId":{"type":"string","description":"Stable question id, as used in the content."},"correct":{"type":"integer","description":"Times the learner answered it correctly."},"misses":{"type":"integer","description":"Times the learner got it wrong."},"needsWork":{"type":"boolean","description":"True when misses are at least as many as correct answers — the questions adaptive sampling brings back first."}},"required":["questionId","correct","misses","needsWork"]},"description":"Per-question history over the learner's 20 most recent attempts, worst first. Empty when they have never answered anything here."},"reviewHints":{"type":"array","items":{"type":"object","properties":{"contentId":{"type":"string","description":"The referenced content id."},"routeSegment":{"type":"string","description":"The parent-owned route segment for this placement."},"title":{"type":"string"},"score":{"type":"integer"},"total":{"type":"integer"}},"required":["contentId","routeSegment","title","score","total"]},"description":"The root content's direct references whose latest quiz score sits below the mastery bar (70%) — 'they struggled here, send them back'. Empty when nothing needs work."}},"required":["contentId","userId","lastQuiz","questions","reviewHints"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/contents/{id}/enrollment-requests":{"get":{"tags":["Learners"],"operationId":"listEnrollmentRequests","summary":"List pending enrollment requests","description":"The content's approval queue, oldest first, with each learner's intake answers. Paid requests expose their exact 30-day `expiresAt`; free requests return null. When `refundPending` is true, do not attempt a manual decision — the daily refund job owns it.","parameters":[{"name":"id","in":"path","required":true,"description":"The content id.","schema":{"type":"string"}}],"responses":{"200":{"description":"List pending enrollment requests.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string","description":"The requesting Cursare user id."},"name":{"type":"string"},"email":{"type":"string","format":"email"},"requestedAt":{"type":"string","format":"date-time"},"status":{"type":"string","enum":["pending","approved","rejected","expired"],"description":"Persistent decision state. The approval queue normally returns pending rows; rejected/expired rows remain visible only while their refund needs attention."},"expiresAt":{"type":["string","null"],"format":"date-time","description":"Paid requests only: the exact instant 30 days after creation when approval and manual rejection become unavailable. Null means a free request with no automatic expiry."},"refundPending":{"type":"boolean","description":"True while a rejected or expired paid request is waiting for provider-confirmed refund. The historical request itself is never removed by that refund."},"answers":{"type":["object","null"],"additionalProperties":{"type":"string"},"description":"The learner's intake-form answers (question id → answer), if collected."}},"required":["id","userId","name","email","requestedAt","status","expiresAt","refundPending","answers"]}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/enrollment-requests/summary":{"get":{"tags":["Learners"],"operationId":"getPendingRequestSummary","summary":"Count pending enrollment requests per course","description":"The approvals inbox at a glance, org-wide: how many people are waiting on staff approval, grouped by course and ordered busiest first. Cheap enough to poll — call it to say 'you have N people waiting across M courses', then drill into a specific course with `listEnrollmentRequests` to see who they are and approve or reject them. Owner/admin sees the whole organization; other members see only courses they own or whose owning team grants them the `learners` role.","responses":{"200":{"description":"Count pending enrollment requests per course.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"pending":{"type":"integer","description":"Total pending requests across the org."},"contents":{"type":"array","items":{"type":"object","properties":{"contentId":{"type":"string"},"slug":{"type":"string","description":"The course's slug — requests only target courses."},"pending":{"type":"integer","description":"Requests waiting on this course."}},"required":["contentId","slug","pending"]},"description":"Courses with at least one waiting request, most requests first."}},"required":["pending","contents"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/enrollment-requests/{id}/approve":{"post":{"tags":["Learners"],"operationId":"approveEnrollmentRequest","summary":"Approve an enrollment request","description":"Enrolls the learner (the seat cap still applies) and records the request as approved. The intake answers collected with the request travel onto the enrollment. A paid request cannot be approved at or after its 30-day expiry; it is waiting for automatic refund.","parameters":[{"name":"id","in":"path","required":true,"description":"The enrollment request id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"schoolReviewConfirmed":{"description":"Confirms that authorized staff checked the minor's age, guardian relationship and authorization. Required for minor enrollment approval.","type":"boolean"}}}}}},"responses":{"200":{"description":"Approve an enrollment request.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"approved":{"type":"boolean","const":true}},"required":["approved"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/enrollment-requests/{id}/reject":{"post":{"tags":["Learners"],"operationId":"rejectEnrollmentRequest","summary":"Reject an enrollment request","description":"Records the request as rejected — the learner may ask again later. A paid, unrefunded purchase is refunded automatically; if that refund fails the rejection still stands, `refundIssued` is false, and the daily worker retries it. An optional `reason` is emailed to the learner best-effort. Send `{}` to reject without a note. An expired paid request cannot be rejected manually because its row is the durable retry queue for the daily refund.","parameters":[{"name":"id","in":"path","required":true,"description":"The enrollment request id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string"}}}}}},"responses":{"200":{"description":"Reject an enrollment request.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"rejected":{"type":"boolean","const":true},"refundIssued":{"type":"boolean","description":"Whether a paid purchase was refunded — false when there was nothing to refund or the automatic refund failed."}},"required":["rejected","refundIssued"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/contents/{id}/cohorts":{"get":{"tags":["Cohorts"],"operationId":"listContentCohorts","summary":"List a content's cohorts","description":"Every cohort on the content, with its tutor, roster, and (for dated cohorts) schedule.","parameters":[{"name":"id","in":"path","required":true,"description":"The content id.","schema":{"type":"string"}}],"responses":{"200":{"description":"List a content's cohorts.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"offerId":{"type":"string","description":"The one offer whose learners belong to this cohort."},"name":{"type":"string"},"mode":{"type":"string","enum":["open","closed"],"description":"`open` = learners self-join; `closed` = staff assigns membership."},"tutorUserId":{"description":"The cohort's tutor — a moderator for this cohort only.","type":["string","null"]},"tutorName":{"type":["string","null"]},"startsAt":{"type":["string","null"],"format":"date-time","description":"Dated cohorts only. Null on evergreen cohorts."},"endsAt":{"type":["string","null"],"format":"date-time"},"seatLimit":{"type":["integer","null"],"description":"Seat cap for this cohort. Null = unlimited."},"enrollClosesAt":{"type":["string","null"],"format":"date-time","description":"Optional earlier enrollment cutoff; enrollment closes at `endsAt` when null."},"members":{"type":"array","items":{"type":"object","properties":{"userId":{"type":"string"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"image":{"type":["string","null"]},"role":{"type":"string","enum":["member","star"],"description":"`star` is a peer-recognition badge granted by the tutor or staff."}},"required":["userId","name","email","image","role"]}}},"required":["id","offerId","name","mode","tutorUserId","tutorName","startsAt","endsAt","seatLimit","enrollClosesAt","members"]}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"tags":["Cohorts"],"operationId":"createCohort","summary":"Create a cohort","description":"On a cohort-delivered offer the cohort requires `startsAt` and `endsAt`. A tutor must hold the cohort role on the course's team (or be its owner) or be an enrolled learner.","parameters":[{"name":"id","in":"path","required":true,"description":"The content id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Cohort name, up to 80 characters."},"offerId":{"type":"string","description":"Owning offer. Omit to use the course's primary offer."},"mode":{"type":"string","enum":["open","closed"],"description":"`open` = learners self-join; `closed` = staff assigns. Defaults to `open`."},"tutorUserId":{"description":"The cohort's tutor (Cursare user id). Null or omitted = no tutor.","type":["string","null"]},"startsAt":{"type":"string","format":"date-time","description":"Cohort start. Required for cohort-delivered offers; drip anchors here."},"endsAt":{"type":"string","format":"date-time","description":"Cohort end. Required for cohort-delivered offers."},"seatLimit":{"type":["integer","null"],"minimum":1,"description":"Seat cap for this cohort. Null or omitted = unlimited."},"enrollClosesAt":{"type":"string","format":"date-time","description":"Optional enrollment cutoff before `endsAt`."}},"required":["name"]}}}},"responses":{"201":{"description":"Create a cohort.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"offerId":{"type":"string"},"name":{"type":"string"},"mode":{"type":"string","enum":["open","closed"]},"tutorUserId":{"type":["string","null"]}},"required":["id","offerId","name","mode","tutorUserId"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/cohorts/{id}":{"patch":{"tags":["Cohorts"],"operationId":"updateCohort","summary":"Update a cohort","description":"Rename, switch open/closed, (re)assign the tutor, or adjust the schedule/seat cap. Only the fields present in the body are changed; `null` clears a nullable field. A cohort on a cohort-delivered offer cannot have its start or end cleared.","parameters":[{"name":"id","in":"path","required":true,"description":"The cohort id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"mode":{"type":"string","enum":["open","closed"]},"tutorUserId":{"description":"The cohort's tutor (Cursare user id). Null removes the tutor.","type":["string","null"]},"startsAt":{"type":["string","null"],"format":"date-time"},"endsAt":{"type":["string","null"],"format":"date-time"},"seatLimit":{"type":["integer","null"],"minimum":1,"description":"Null = unlimited."},"enrollClosesAt":{"type":["string","null"],"format":"date-time","description":"Null falls back to closing enrollment at `endsAt`."}}}}}},"responses":{"200":{"description":"Update a cohort.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"updated":{"type":"boolean","const":true}},"required":["id","updated"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"tags":["Cohorts"],"operationId":"deleteCohort","summary":"Delete a cohort","description":"Removes an empty cohort and its discussion. A cohort referenced by a learner or pending request is refused (400) — move them first.","parameters":[{"name":"id","in":"path","required":true,"description":"The cohort id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Delete a cohort.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"deleted":{"type":"boolean","const":true}},"required":["id","deleted"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/cohorts/{id}/members":{"post":{"tags":["Cohorts"],"operationId":"addCohortMember","summary":"Add or move a learner into a cohort","description":"The user must have an active enrollment in the cohort's exact offer. The enrollment stores at most one cohort — assigning another replaces it.","parameters":[{"name":"id","in":"path","required":true,"description":"The cohort id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"userId":{"type":"string","description":"The Cursare user id of an enrolled learner."}},"required":["userId"]}}}},"responses":{"201":{"description":"Add or move a learner into a cohort.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"cohortId":{"type":"string"},"userId":{"type":"string"},"assigned":{"type":"boolean","const":true}},"required":["cohortId","userId","assigned"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/cohorts/{id}/members/{userId}":{"delete":{"tags":["Cohorts"],"operationId":"removeCohortMember","summary":"Remove a learner from a cohort","description":"Clears the cohort from a self-paced learner. Cohort-delivery learners must be moved instead.","parameters":[{"name":"id","in":"path","required":true,"description":"The cohort id.","schema":{"type":"string"}},{"name":"userId","in":"path","required":true,"description":"The Cursare user id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Remove a learner from a cohort.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"cohortId":{"type":"string"},"userId":{"type":"string"},"removed":{"type":"boolean","const":true}},"required":["cohortId","userId","removed"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"tags":["Cohorts"],"operationId":"setCohortMemberRole","summary":"Set a member's Star badge","description":"Promote a member to `star` (peer recognition — a badge, never moderation power) or demote them back to `member`.","parameters":[{"name":"id","in":"path","required":true,"description":"The cohort id.","schema":{"type":"string"}},{"name":"userId","in":"path","required":true,"description":"The Cursare user id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"role":{"type":"string","enum":["member","star"]}},"required":["role"]}}}},"responses":{"200":{"description":"Set a member's Star badge.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"cohortId":{"type":"string"},"userId":{"type":"string"},"role":{"type":"string","enum":["member","star"]}},"required":["cohortId","userId","role"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/cohorts/{id}/discussion":{"get":{"tags":["Cohorts"],"operationId":"listCohortDiscussion","summary":"List a cohort's discussion","description":"The cohort's discussion threads — top-level posts (pinned first, then newest) with their replies. Read-only: posts are authored by enrolled members on the course page.","parameters":[{"name":"id","in":"path","required":true,"description":"The cohort id.","schema":{"type":"string"}}],"responses":{"200":{"description":"List a cohort's discussion.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string","description":"The author's user id."},"authorName":{"type":"string"},"authorImage":{"type":["string","null"]},"badge":{"type":["string","null"],"enum":["instructor","tutor","star"],"description":"The author's standing in this cohort, by precedence: instructor (content staff) > tutor (this cohort's) > star (a promoted member). Null for a plain member."},"body":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"sectionId":{"description":"The course section this question is tagged to, if any (top-level only).","type":["string","null"]},"resolvedAt":{"type":["string","null"],"format":"date-time","description":"When the question was marked answered, or null."},"pinnedAt":{"type":["string","null"],"format":"date-time","description":"When the post was pinned, or null."},"replies":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string","description":"The author's user id."},"authorName":{"type":"string"},"authorImage":{"type":["string","null"]},"badge":{"type":["string","null"],"enum":["instructor","tutor","star"],"description":"The author's standing in this cohort, by precedence: instructor (content staff) > tutor (this cohort's) > star (a promoted member). Null for a plain member."},"body":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","userId","authorName","authorImage","badge","body","createdAt"]},"description":"Replies to this post, oldest first (one level deep)."}},"required":["id","userId","authorName","authorImage","badge","body","createdAt","sectionId","resolvedAt","pinnedAt","replies"]}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"tags":["Cohorts"],"operationId":"createCohortDiscussionPost","summary":"Post to a cohort's discussion","description":"Create a top-level post, or a reply (set `parentId`). Posted AS a specified author (`authorEmail`) who must be an org staff member or this cohort's tutor — the API never posts as a plain learner, so it can't forge a member's post. Fires `discussion.post.created`.","parameters":[{"name":"id","in":"path","required":true,"description":"The cohort id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"body":{"type":"string","minLength":1,"maxLength":5000,"description":"The post text."},"authorEmail":{"type":"string","format":"email","description":"The author — must be an org staff member or this cohort's tutor."},"parentId":{"description":"Set to reply to a top-level post; omit for a new top-level post.","type":"string"},"sectionId":{"description":"Tag a top-level post to a course section (ignored on replies).","type":"string"}},"required":["body","authorEmail"]}}}},"responses":{"201":{"description":"Post to a cohort's discussion.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The created post id."}},"required":["id"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/discussion/{postId}/resolve":{"post":{"tags":["Cohorts"],"operationId":"resolveDiscussionPost","summary":"Resolve or reopen a question","description":"Mark a top-level question answered, or reopen it. Staff or the cohort tutor.","parameters":[{"name":"postId","in":"path","required":true,"description":"The post id (a top-level question).","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"resolved":{"type":"boolean","description":"true marks it answered; false reopens it."}},"required":["resolved"]}}}},"responses":{"200":{"description":"Resolve or reopen a question.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"resolved":{"type":"boolean"}},"required":["resolved"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/discussion/{postId}/pin":{"post":{"tags":["Cohorts"],"operationId":"pinDiscussionPost","summary":"Pin or unpin a post","description":"Pin a top-level post to the top of the discussion, or unpin it. Staff or the cohort tutor.","parameters":[{"name":"postId","in":"path","required":true,"description":"The post id (top-level).","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"pinned":{"type":"boolean","description":"true pins it; false unpins it."}},"required":["pinned"]}}}},"responses":{"200":{"description":"Pin or unpin a post.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"pinned":{"type":"boolean"}},"required":["pinned"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/discussion/{postId}":{"delete":{"tags":["Cohorts"],"operationId":"deleteDiscussionPost","summary":"Delete a post","description":"Delete a post. Deleting a top-level post also removes its replies. The author, the cohort tutor, or staff.","parameters":[{"name":"postId","in":"path","required":true,"description":"The post id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Delete a post.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"deleted":{"type":"boolean","const":true}},"required":["deleted"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/intake-forms":{"get":{"tags":["Intake forms"],"operationId":"listIntakeForms","summary":"List intake forms","description":"The org's reusable intake forms, newest first, each with a `usageCount` of the contents currently attaching it.","responses":{"200":{"description":"List intake forms.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/$defs/IntakeForm"},"$defs":{"IntakeForm":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"questions":{"type":"array","items":{"$ref":"#/$defs/IntakeQuestion"}},"usageCount":{"type":"integer","description":"How many contents currently attach the form (GET responses only)."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","name","questions","createdAt","updatedAt"],"description":"A reusable enrollment questionnaire — contents reference it live, so edits apply everywhere it's attached."},"IntakeQuestion":{"type":"object","properties":{"id":{"type":"string","description":"Stable server-assigned id — learner answers are keyed by it."},"label":{"type":"string"},"description":{"type":"string","description":"Helper text shown under the label."},"type":{"type":"string","enum":["text","textarea","select","file","date","number","email","phone"],"description":"`file` answers store the uploaded file's URL; `date` an ISO date (YYYY-MM-DD)."},"options":{"type":"array","items":{"type":"string"},"description":"Choices for `select` questions; absent for the other types."},"required":{"type":"boolean"}},"required":["id","label","type","required"],"description":"One enrollment question a learner answers at intake."}}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"tags":["Intake forms"],"operationId":"createIntakeForm","summary":"Create an intake form","description":"A named set of enrollment questions (max 10). Attach it to a content with `PATCH /contents/{id}` and its `intakeFormId` field.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"questions":{"maxItems":10,"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":300},"type":{"type":"string","enum":["text","textarea","select","file","date","number","email","phone"]},"options":{"maxItems":20,"type":"array","items":{"type":"string"}},"required":{"type":"boolean"}},"required":["label","type"]}}},"required":["name"]}}}},"responses":{"201":{"description":"Create an intake form.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"questions":{"type":"array","items":{"$ref":"#/$defs/IntakeQuestion"}},"usageCount":{"type":"integer","description":"How many contents currently attach the form (GET responses only)."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","name","questions","createdAt","updatedAt"],"description":"A reusable enrollment questionnaire — contents reference it live, so edits apply everywhere it's attached.","$defs":{"IntakeForm":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"questions":{"type":"array","items":{"$ref":"#/$defs/IntakeQuestion"}},"usageCount":{"type":"integer","description":"How many contents currently attach the form (GET responses only)."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","name","questions","createdAt","updatedAt"],"description":"A reusable enrollment questionnaire — contents reference it live, so edits apply everywhere it's attached."},"IntakeQuestion":{"type":"object","properties":{"id":{"type":"string","description":"Stable server-assigned id — learner answers are keyed by it."},"label":{"type":"string"},"description":{"type":"string","description":"Helper text shown under the label."},"type":{"type":"string","enum":["text","textarea","select","file","date","number","email","phone"],"description":"`file` answers store the uploaded file's URL; `date` an ISO date (YYYY-MM-DD)."},"options":{"type":"array","items":{"type":"string"},"description":"Choices for `select` questions; absent for the other types."},"required":{"type":"boolean"}},"required":["id","label","type","required"],"description":"One enrollment question a learner answers at intake."}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/intake-forms/{id}":{"get":{"tags":["Intake forms"],"operationId":"getIntakeForm","summary":"Get an intake form","parameters":[{"name":"id","in":"path","required":true,"description":"The intake form id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Get an intake form.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"questions":{"type":"array","items":{"$ref":"#/$defs/IntakeQuestion"}},"usageCount":{"type":"integer","description":"How many contents currently attach the form (GET responses only)."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","name","questions","createdAt","updatedAt"],"description":"A reusable enrollment questionnaire — contents reference it live, so edits apply everywhere it's attached.","$defs":{"IntakeForm":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"questions":{"type":"array","items":{"$ref":"#/$defs/IntakeQuestion"}},"usageCount":{"type":"integer","description":"How many contents currently attach the form (GET responses only)."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","name","questions","createdAt","updatedAt"],"description":"A reusable enrollment questionnaire — contents reference it live, so edits apply everywhere it's attached."},"IntakeQuestion":{"type":"object","properties":{"id":{"type":"string","description":"Stable server-assigned id — learner answers are keyed by it."},"label":{"type":"string"},"description":{"type":"string","description":"Helper text shown under the label."},"type":{"type":"string","enum":["text","textarea","select","file","date","number","email","phone"],"description":"`file` answers store the uploaded file's URL; `date` an ISO date (YYYY-MM-DD)."},"options":{"type":"array","items":{"type":"string"},"description":"Choices for `select` questions; absent for the other types."},"required":{"type":"boolean"}},"required":["id","label","type","required"],"description":"One enrollment question a learner answers at intake."}}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"tags":["Intake forms"],"operationId":"updateIntakeForm","summary":"Update an intake form","description":"Rename the form and/or replace its questions. The reference is live — changes apply everywhere the form is attached. Keep question ids stable so existing answers stay linked.","parameters":[{"name":"id","in":"path","required":true,"description":"The intake form id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"questions":{"maxItems":10,"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":300},"type":{"type":"string","enum":["text","textarea","select","file","date","number","email","phone"]},"options":{"maxItems":20,"type":"array","items":{"type":"string"}},"required":{"type":"boolean"}},"required":["label","type"]}}}}}}},"responses":{"200":{"description":"Update an intake form.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"questions":{"type":"array","items":{"$ref":"#/$defs/IntakeQuestion"}},"usageCount":{"type":"integer","description":"How many contents currently attach the form (GET responses only)."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","name","questions","createdAt","updatedAt"],"description":"A reusable enrollment questionnaire — contents reference it live, so edits apply everywhere it's attached.","$defs":{"IntakeForm":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"questions":{"type":"array","items":{"$ref":"#/$defs/IntakeQuestion"}},"usageCount":{"type":"integer","description":"How many contents currently attach the form (GET responses only)."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","name","questions","createdAt","updatedAt"],"description":"A reusable enrollment questionnaire — contents reference it live, so edits apply everywhere it's attached."},"IntakeQuestion":{"type":"object","properties":{"id":{"type":"string","description":"Stable server-assigned id — learner answers are keyed by it."},"label":{"type":"string"},"description":{"type":"string","description":"Helper text shown under the label."},"type":{"type":"string","enum":["text","textarea","select","file","date","number","email","phone"],"description":"`file` answers store the uploaded file's URL; `date` an ISO date (YYYY-MM-DD)."},"options":{"type":"array","items":{"type":"string"},"description":"Choices for `select` questions; absent for the other types."},"required":{"type":"boolean"}},"required":["id","label","type","required"],"description":"One enrollment question a learner answers at intake."}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"tags":["Intake forms"],"operationId":"deleteIntakeForm","summary":"Delete an intake form","description":"Contents pointing at the form get their `intakeFormId` set to null and fall back to their own inline questions. Answers already collected are kept.","parameters":[{"name":"id","in":"path","required":true,"description":"The intake form id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Delete an intake form.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"deleted":{"type":"boolean","const":true}},"required":["id","deleted"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/campaigns":{"get":{"tags":["Campaigns"],"operationId":"listCampaigns","summary":"List campaigns","description":"Every campaign in the organization. Pass `contentId` to get the set that applies to one content (its own plus the org's global campaigns).","parameters":[{"name":"contentId","in":"query","description":"Only campaigns that apply to this content (its own + global).","schema":{"type":"string"}}],"responses":{"200":{"description":"List campaigns.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Campaign"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"tags":["Campaigns"],"operationId":"createCampaign","summary":"Create a campaign","description":"Provide `percentOff` or `amountOff` (minor units) — not both. Omit `offerIds` (or pass `null`/`[]`) for a GLOBAL campaign that applies to every paid offer. `public` campaigns show a de/por price on the storefront and auto-apply at checkout.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","minLength":3,"maxLength":24,"pattern":"^[a-zA-Z0-9-]+$","description":"The code learners type at checkout."},"offerIds":{"type":["array","null"],"items":{"type":"string"},"description":"Scope to these PAID offers. Omit / null / [] for a GLOBAL, org-wide campaign."},"percentOff":{"type":"integer","minimum":1,"maximum":100},"amountOff":{"type":"integer","minimum":1,"maximum":100000000,"description":"Discount in the content currency's minor unit (cents)."},"maxRedemptions":{"type":"integer","minimum":1,"maximum":10000000,"description":"Optional redemption cap."},"expiresAt":{"anyOf":[{"type":"string","format":"date"},{"type":"string","format":"date-time"}],"description":"Optional expiry as an ISO date or offset date-time — the code stops applying after it."},"public":{"type":"boolean","description":"Advertise a de/por price on the storefront and auto-apply at checkout."},"image":{"type":"string","description":"Optional promo banner image URL."},"disclaimer":{"type":"string","description":"Optional fine print shown with the public promo."}},"required":["code"]}}}},"responses":{"201":{"description":"Create a campaign.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Campaign"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/campaigns/{id}":{"patch":{"tags":["Campaigns"],"operationId":"updateCampaign","summary":"Update a campaign","description":"Change presentation, limits and scope — never the code or discount.","parameters":[{"name":"id","in":"path","required":true,"description":"The campaign id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"active":{"type":"boolean"},"public":{"type":"boolean"},"image":{"type":["string","null"]},"disclaimer":{"type":["string","null"]},"maxRedemptions":{"type":["integer","null"],"minimum":1,"maximum":10000000},"expiresAt":{"anyOf":[{"anyOf":[{"type":"string","format":"date"},{"type":"string","format":"date-time"}],"description":"Optional expiry as an ISO date or offset date-time — the code stops applying after it."},{"type":"null"}]},"offerIds":{"type":["array","null"],"items":{"type":"string"},"description":"Re-scope to these PAID offers. null / [] = GLOBAL, org-wide."}}}}}},"responses":{"200":{"description":"Update a campaign.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Campaign"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"tags":["Campaigns"],"operationId":"deleteCampaign","summary":"Delete a campaign","description":"Past redemptions keep their access.","parameters":[{"name":"id","in":"path","required":true,"description":"The campaign id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Delete a campaign.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"deleted":{"type":"boolean","const":true}},"required":["id","deleted"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/teams":{"get":{"tags":["Teams"],"operationId":"listTeams","summary":"List teams","description":"The org's teams with their members.","responses":{"200":{"description":"List teams.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Team"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"tags":["Teams"],"operationId":"createTeam","summary":"Create a team","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":2,"maxLength":60},"logo":{"type":["string","null"]}},"required":["name"]}}}},"responses":{"201":{"description":"Create a team.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/teams/{id}":{"get":{"tags":["Teams"],"operationId":"getTeam","summary":"Get a team","parameters":[{"name":"id","in":"path","required":true,"description":"The team id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Get a team.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Team"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"tags":["Teams"],"operationId":"updateTeam","summary":"Update a team's name, logo or bio","description":"Org-admin only. Every field is optional — send just the ones you want to change; omitted fields are left alone. Send `null` for `logo` or `bio` to clear them.","parameters":[{"name":"id","in":"path","required":true,"description":"The team id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":2,"maxLength":60},"logo":{"type":["string","null"]},"bio":{"type":["string","null"],"maxLength":500}}}}}},"responses":{"200":{"description":"Update a team's name, logo or bio.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"logo":{"type":["string","null"]},"bio":{"type":["string","null"]}},"required":["id","name","logo","bio"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"tags":["Teams"],"operationId":"deleteTeam","summary":"Delete a team","description":"Dissolves the team; its members stay in the org.","parameters":[{"name":"id","in":"path","required":true,"description":"The team id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Delete a team.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"deleted":{"type":"boolean","const":true}},"required":["id","deleted"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/teams/{id}/members":{"post":{"tags":["Teams"],"operationId":"addTeamMember","summary":"Add a member to a team","description":"Identify the org member by `userId` or `email` (one is required). Adding someone grants NOTHING on its own — a member with no roles is just listed on the team. Follow this call with `setTeamMemberRoles` to give them their responsibilities, otherwise the team is half-configured.","parameters":[{"name":"id","in":"path","required":true,"description":"The team id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"userId":{"type":"string","minLength":1},"email":{"type":"string","format":"email"}}}}}},"responses":{"201":{"description":"Add a member to a team.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"teamId":{"type":"string"},"userId":{"type":"string"}},"required":["teamId","userId"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/teams/{id}/members/{userId}":{"delete":{"tags":["Teams"],"operationId":"removeTeamMember","summary":"Remove a member from a team","parameters":[{"name":"id","in":"path","required":true,"description":"The team id.","schema":{"type":"string"}},{"name":"userId","in":"path","required":true,"description":"The Cursare user id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Remove a member from a team.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"teamId":{"type":"string"},"userId":{"type":"string"},"removed":{"type":"boolean","const":true}},"required":["teamId","userId","removed"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/teams/{id}/members/{userId}/roles":{"put":{"tags":["Teams"],"operationId":"setTeamMemberRoles","summary":"Set a team member's roles","description":"Org-admin only. Replaces the member's WHOLE role set on this team — the roles you send become the roles they have, so include the ones you want to keep. Send `[]` to strip every responsibility (they stay on the team, but authorize nothing). The user must already be on the team: call `addTeamMember` first. This is what turns a listed member into someone who can actually work on the team's courses, so run it right after adding anyone.","parameters":[{"name":"id","in":"path","required":true,"description":"The team id.","schema":{"type":"string"}},{"name":"userId","in":"path","required":true,"description":"The Cursare user id of the team member.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"roles":{"type":"array","items":{"type":"string","enum":["editor","finance","cohort","learners"]}}},"required":["roles"]}}}},"responses":{"200":{"description":"Set a team member's roles.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"teamId":{"type":"string"},"userId":{"type":"string"},"roles":{"type":"array","items":{"type":"string","enum":["editor","finance","cohort","learners"],"description":"`editor` = edit the team's courses and their content; `finance` = change pricing, offers and campaigns on them; `cohort` = manage their cohorts (cohorts) and act as tutor; `learners` = manage enrollment, progress, intake answers and attachments."},"description":"The member's roles after the update."}},"required":["teamId","userId","roles"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/purchases":{"get":{"tags":["Sales"],"operationId":"listPurchases","summary":"List purchases","description":"The org's purchase ledger, newest first and paginated. Read-only — to refund a purchase, call `POST /purchases/{id}/refund`.","parameters":[{"name":"contentId","in":"query","description":"Only purchases of this content.","schema":{"type":"string"}},{"name":"userId","in":"query","description":"Only purchases by this Cursare user.","schema":{"type":"string"}},{"name":"status","in":"query","description":"Filter by ledger status.","schema":{"type":"string","enum":["paid","refunded","past_due","canceled"]}},{"name":"from","in":"query","description":"Only purchases made on or after this ISO date.","schema":{"type":"string","format":"date"}},{"name":"to","in":"query","description":"Only purchases made on or before this ISO date.","schema":{"type":"string","format":"date"}},{"name":"page","in":"query","schema":{"default":1,"type":"integer","minimum":1}},{"name":"pageSize","in":"query","schema":{"default":25,"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"List purchases.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"purchases":{"type":"array","items":{"type":"object","properties":{"platformFees":{"type":"array","items":{"type":"object","properties":{"currency":{"type":"string","minLength":3,"maxLength":3,"description":"Settlement currency of the application fee."},"collectedAmount":{"type":"integer","minimum":0,"description":"Provider-confirmed original fees, in minor units."},"refundedAmount":{"type":"integer","minimum":0,"description":"Cumulative returned application fees, in minor units."},"netAmount":{"type":"integer","minimum":0,"description":"Collected minus returned application fees; not seller profit."}},"required":["currency","collectedAmount","refundedAmount","netAmount"]},"description":"Fee balances reconciled from Stripe, grouped by settlement currency. Empty means no fee facts have arrived yet, or no fee was charged. Never add different currencies."},"platformFeeBps":{"type":"integer","minimum":0,"maximum":10000,"description":"Cursare payment fee frozen when checkout started, in basis points (250 = 2.5%). Read-only; only platform administrators can change future commercial terms."},"collectedAmount":{"type":["integer","null"],"minimum":0,"description":"Confirmed payments received so far in minor units, before refunds. Excludes unpaid installments. Null when payment evidence is unavailable."},"platformFeeAmount":{"type":["integer","null"],"minimum":0,"description":"Original Cursare application fees on confirmed payments, in minor units. Not processing fees or a net-profit figure; does not subtract returned application fees. Null when unavailable, zero for a zero-rate purchase."},"id":{"type":"string"},"contentId":{"type":"string"},"contentTitle":{"description":"Null when the content was deleted after the sale.","type":["string","null"]},"userId":{"description":"Null when the buyer's account was deleted.","type":["string","null"]},"buyerName":{"type":["string","null"]},"buyerEmail":{"type":["string","null"]},"learnerUserId":{"description":"The access beneficiary.","type":["string","null"]},"learnerName":{"type":["string","null"]},"learnerEmail":{"type":["string","null"]},"buyerLegalName":{"description":"Legal name the buyer entered at checkout for invoicing.","type":["string","null"]},"buyerTaxId":{"description":"Buyer's tax id for invoicing (CPF/CNPJ in BR, VAT in the EU, …); null if skipped.","type":["string","null"]},"buyerTaxIdType":{"description":"The tax id's country-specific type: `br_cpf`, `br_cnpj`, `eu_vat`, `us_ein`, …","type":["string","null"]},"buyerCountry":{"description":"Buyer's ISO-3166-1 alpha-2 country, when collected.","type":["string","null"]},"amount":{"type":"integer","description":"What was paid, in the currency's minor unit (cents)."},"currency":{"type":"string","description":"ISO currency code, e.g. `BRL`."},"status":{"type":"string","enum":["paid","refunded","past_due","canceled"],"description":"`paid` = settled and un-refunded; `refunded` = money returned; `past_due`/`canceled` = installment-plan health."},"installments":{"type":["integer","null"],"description":"Monthly charges of a payment plan; null for one-time purchases."},"createdAt":{"type":"string","format":"date-time"},"refundedAt":{"type":["string","null"],"format":"date-time"},"withdrawalEligibleUntil":{"type":["string","null"],"format":"date-time"},"refundKind":{"type":["string","null"],"enum":["withdrawal","support","staff","safeguard"]},"refundStatus":{"type":["string","null"],"enum":["requested","processing","refunded","failed","denied"]},"refundRequestedAt":{"type":["string","null"],"format":"date-time"},"refundResolvedAt":{"type":["string","null"],"format":"date-time"},"refundReason":{"type":["string","null"]},"refundResolutionReason":{"type":["string","null"]},"refundedAmount":{"type":["integer","null"],"description":"Amount returned, in the currency's minor unit."},"sellerSnapshot":{"type":["object","null"],"properties":{"legalName":{"type":"string"},"taxIdType":{"type":"string","enum":["br_cpf","br_cnpj","us_ein","us_individual","eu_vat","national"]},"taxId":{"description":"Public seller tax id; null when the identifier is private in its jurisdiction.","type":["string","null"]},"address":{"type":"object","properties":{"line1":{"type":"string"},"line2":{"type":"string"},"city":{"type":"string"},"region":{"type":"string"},"postalCode":{"type":"string"},"country":{"type":"string"}},"required":["line1","city","region","postalCode","country"]},"supportEmail":{"type":"string","format":"email"},"supportUrl":{"type":["string","null"]},"supportPhone":{"type":["string","null"]}},"required":["legalName","taxIdType","taxId","address","supportEmail","supportUrl","supportPhone"],"description":"The seller identity and support channels disclosed when the buyer paid."},"contractSnapshot":{"type":["object","null"],"properties":{"contentTitle":{"type":"string"},"offerName":{"type":"string"},"amount":{"type":"integer"},"currency":{"type":"string"},"installmentAmounts":{"type":"array","items":{"type":"integer"}},"accessTerms":{"type":"string"},"withdrawalDays":{"type":"integer"},"termsVersion":{"type":"integer"}},"required":["contentTitle","offerName","amount","currency","installmentAmounts","accessTerms","withdrawalDays","termsVersion"],"description":"The course, offer, exact installment schedule and access terms accepted at checkout."}},"required":["platformFees","platformFeeBps","collectedAmount","platformFeeAmount","id","contentId","contentTitle","userId","buyerName","buyerEmail","learnerUserId","learnerName","learnerEmail","buyerLegalName","buyerTaxId","buyerTaxIdType","buyerCountry","amount","currency","status","installments","createdAt","refundedAt","withdrawalEligibleUntil","refundKind","refundStatus","refundRequestedAt","refundResolvedAt","refundReason","refundResolutionReason","refundedAmount","sellerSnapshot","contractSnapshot"]}},"page":{"type":"integer"},"pageSize":{"type":"integer"},"total":{"type":"integer"}},"required":["purchases","page","pageSize","total"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/purchases/{id}":{"get":{"tags":["Sales"],"operationId":"getPurchase","summary":"Get a purchase","description":"One ledger row, org-scoped. Read-only — to refund it, call `POST /purchases/{id}/refund`.","parameters":[{"name":"id","in":"path","required":true,"description":"The purchase id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Get a purchase.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"platformFees":{"type":"array","items":{"type":"object","properties":{"currency":{"type":"string","minLength":3,"maxLength":3,"description":"Settlement currency of the application fee."},"collectedAmount":{"type":"integer","minimum":0,"description":"Provider-confirmed original fees, in minor units."},"refundedAmount":{"type":"integer","minimum":0,"description":"Cumulative returned application fees, in minor units."},"netAmount":{"type":"integer","minimum":0,"description":"Collected minus returned application fees; not seller profit."}},"required":["currency","collectedAmount","refundedAmount","netAmount"]},"description":"Fee balances reconciled from Stripe, grouped by settlement currency. Empty means no fee facts have arrived yet, or no fee was charged. Never add different currencies."},"platformFeeBps":{"type":"integer","minimum":0,"maximum":10000,"description":"Cursare payment fee frozen when checkout started, in basis points (250 = 2.5%). Read-only; only platform administrators can change future commercial terms."},"collectedAmount":{"type":["integer","null"],"minimum":0,"description":"Confirmed payments received so far in minor units, before refunds. Excludes unpaid installments. Null when payment evidence is unavailable."},"platformFeeAmount":{"type":["integer","null"],"minimum":0,"description":"Original Cursare application fees on confirmed payments, in minor units. Not processing fees or a net-profit figure; does not subtract returned application fees. Null when unavailable, zero for a zero-rate purchase."},"id":{"type":"string"},"contentId":{"type":"string"},"contentTitle":{"description":"Null when the content was deleted after the sale.","type":["string","null"]},"userId":{"description":"Null when the buyer's account was deleted.","type":["string","null"]},"buyerName":{"type":["string","null"]},"buyerEmail":{"type":["string","null"]},"learnerUserId":{"description":"The access beneficiary.","type":["string","null"]},"learnerName":{"type":["string","null"]},"learnerEmail":{"type":["string","null"]},"buyerLegalName":{"description":"Legal name the buyer entered at checkout for invoicing.","type":["string","null"]},"buyerTaxId":{"description":"Buyer's tax id for invoicing (CPF/CNPJ in BR, VAT in the EU, …); null if skipped.","type":["string","null"]},"buyerTaxIdType":{"description":"The tax id's country-specific type: `br_cpf`, `br_cnpj`, `eu_vat`, `us_ein`, …","type":["string","null"]},"buyerCountry":{"description":"Buyer's ISO-3166-1 alpha-2 country, when collected.","type":["string","null"]},"amount":{"type":"integer","description":"What was paid, in the currency's minor unit (cents)."},"currency":{"type":"string","description":"ISO currency code, e.g. `BRL`."},"status":{"type":"string","enum":["paid","refunded","past_due","canceled"],"description":"`paid` = settled and un-refunded; `refunded` = money returned; `past_due`/`canceled` = installment-plan health."},"installments":{"type":["integer","null"],"description":"Monthly charges of a payment plan; null for one-time purchases."},"createdAt":{"type":"string","format":"date-time"},"refundedAt":{"type":["string","null"],"format":"date-time"},"withdrawalEligibleUntil":{"type":["string","null"],"format":"date-time"},"refundKind":{"type":["string","null"],"enum":["withdrawal","support","staff","safeguard"]},"refundStatus":{"type":["string","null"],"enum":["requested","processing","refunded","failed","denied"]},"refundRequestedAt":{"type":["string","null"],"format":"date-time"},"refundResolvedAt":{"type":["string","null"],"format":"date-time"},"refundReason":{"type":["string","null"]},"refundResolutionReason":{"type":["string","null"]},"refundedAmount":{"type":["integer","null"],"description":"Amount returned, in the currency's minor unit."},"sellerSnapshot":{"type":["object","null"],"properties":{"legalName":{"type":"string"},"taxIdType":{"type":"string","enum":["br_cpf","br_cnpj","us_ein","us_individual","eu_vat","national"]},"taxId":{"description":"Public seller tax id; null when the identifier is private in its jurisdiction.","type":["string","null"]},"address":{"type":"object","properties":{"line1":{"type":"string"},"line2":{"type":"string"},"city":{"type":"string"},"region":{"type":"string"},"postalCode":{"type":"string"},"country":{"type":"string"}},"required":["line1","city","region","postalCode","country"]},"supportEmail":{"type":"string","format":"email"},"supportUrl":{"type":["string","null"]},"supportPhone":{"type":["string","null"]}},"required":["legalName","taxIdType","taxId","address","supportEmail","supportUrl","supportPhone"],"description":"The seller identity and support channels disclosed when the buyer paid."},"contractSnapshot":{"type":["object","null"],"properties":{"contentTitle":{"type":"string"},"offerName":{"type":"string"},"amount":{"type":"integer"},"currency":{"type":"string"},"installmentAmounts":{"type":"array","items":{"type":"integer"}},"accessTerms":{"type":"string"},"withdrawalDays":{"type":"integer"},"termsVersion":{"type":"integer"}},"required":["contentTitle","offerName","amount","currency","installmentAmounts","accessTerms","withdrawalDays","termsVersion"],"description":"The course, offer, exact installment schedule and access terms accepted at checkout."}},"required":["platformFees","platformFeeBps","collectedAmount","platformFeeAmount","id","contentId","contentTitle","userId","buyerName","buyerEmail","learnerUserId","learnerName","learnerEmail","buyerLegalName","buyerTaxId","buyerTaxIdType","buyerCountry","amount","currency","status","installments","createdAt","refundedAt","withdrawalEligibleUntil","refundKind","refundStatus","refundRequestedAt","refundResolvedAt","refundReason","refundResolutionReason","refundedAmount","sellerSnapshot","contractSnapshot"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/contents/{id}/purchases":{"get":{"tags":["Sales"],"operationId":"listContentPurchases","summary":"List a content's purchases","description":"The purchase ledger of one content, newest first and paginated. Read-only — to refund a purchase, call `POST /purchases/{id}/refund`.","parameters":[{"name":"id","in":"path","required":true,"description":"The content id.","schema":{"type":"string"}},{"name":"userId","in":"query","description":"Only purchases by this Cursare user.","schema":{"type":"string"}},{"name":"status","in":"query","description":"Filter by ledger status.","schema":{"type":"string","enum":["paid","refunded","past_due","canceled"]}},{"name":"from","in":"query","description":"Only purchases made on or after this ISO date.","schema":{"type":"string","format":"date"}},{"name":"to","in":"query","description":"Only purchases made on or before this ISO date.","schema":{"type":"string","format":"date"}},{"name":"page","in":"query","schema":{"default":1,"type":"integer","minimum":1}},{"name":"pageSize","in":"query","schema":{"default":25,"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"List a content's purchases.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"purchases":{"type":"array","items":{"type":"object","properties":{"platformFees":{"type":"array","items":{"type":"object","properties":{"currency":{"type":"string","minLength":3,"maxLength":3,"description":"Settlement currency of the application fee."},"collectedAmount":{"type":"integer","minimum":0,"description":"Provider-confirmed original fees, in minor units."},"refundedAmount":{"type":"integer","minimum":0,"description":"Cumulative returned application fees, in minor units."},"netAmount":{"type":"integer","minimum":0,"description":"Collected minus returned application fees; not seller profit."}},"required":["currency","collectedAmount","refundedAmount","netAmount"]},"description":"Fee balances reconciled from Stripe, grouped by settlement currency. Empty means no fee facts have arrived yet, or no fee was charged. Never add different currencies."},"platformFeeBps":{"type":"integer","minimum":0,"maximum":10000,"description":"Cursare payment fee frozen when checkout started, in basis points (250 = 2.5%). Read-only; only platform administrators can change future commercial terms."},"collectedAmount":{"type":["integer","null"],"minimum":0,"description":"Confirmed payments received so far in minor units, before refunds. Excludes unpaid installments. Null when payment evidence is unavailable."},"platformFeeAmount":{"type":["integer","null"],"minimum":0,"description":"Original Cursare application fees on confirmed payments, in minor units. Not processing fees or a net-profit figure; does not subtract returned application fees. Null when unavailable, zero for a zero-rate purchase."},"id":{"type":"string"},"contentId":{"type":"string"},"contentTitle":{"description":"Null when the content was deleted after the sale.","type":["string","null"]},"userId":{"description":"Null when the buyer's account was deleted.","type":["string","null"]},"buyerName":{"type":["string","null"]},"buyerEmail":{"type":["string","null"]},"learnerUserId":{"description":"The access beneficiary.","type":["string","null"]},"learnerName":{"type":["string","null"]},"learnerEmail":{"type":["string","null"]},"buyerLegalName":{"description":"Legal name the buyer entered at checkout for invoicing.","type":["string","null"]},"buyerTaxId":{"description":"Buyer's tax id for invoicing (CPF/CNPJ in BR, VAT in the EU, …); null if skipped.","type":["string","null"]},"buyerTaxIdType":{"description":"The tax id's country-specific type: `br_cpf`, `br_cnpj`, `eu_vat`, `us_ein`, …","type":["string","null"]},"buyerCountry":{"description":"Buyer's ISO-3166-1 alpha-2 country, when collected.","type":["string","null"]},"amount":{"type":"integer","description":"What was paid, in the currency's minor unit (cents)."},"currency":{"type":"string","description":"ISO currency code, e.g. `BRL`."},"status":{"type":"string","enum":["paid","refunded","past_due","canceled"],"description":"`paid` = settled and un-refunded; `refunded` = money returned; `past_due`/`canceled` = installment-plan health."},"installments":{"type":["integer","null"],"description":"Monthly charges of a payment plan; null for one-time purchases."},"createdAt":{"type":"string","format":"date-time"},"refundedAt":{"type":["string","null"],"format":"date-time"},"withdrawalEligibleUntil":{"type":["string","null"],"format":"date-time"},"refundKind":{"type":["string","null"],"enum":["withdrawal","support","staff","safeguard"]},"refundStatus":{"type":["string","null"],"enum":["requested","processing","refunded","failed","denied"]},"refundRequestedAt":{"type":["string","null"],"format":"date-time"},"refundResolvedAt":{"type":["string","null"],"format":"date-time"},"refundReason":{"type":["string","null"]},"refundResolutionReason":{"type":["string","null"]},"refundedAmount":{"type":["integer","null"],"description":"Amount returned, in the currency's minor unit."},"sellerSnapshot":{"type":["object","null"],"properties":{"legalName":{"type":"string"},"taxIdType":{"type":"string","enum":["br_cpf","br_cnpj","us_ein","us_individual","eu_vat","national"]},"taxId":{"description":"Public seller tax id; null when the identifier is private in its jurisdiction.","type":["string","null"]},"address":{"type":"object","properties":{"line1":{"type":"string"},"line2":{"type":"string"},"city":{"type":"string"},"region":{"type":"string"},"postalCode":{"type":"string"},"country":{"type":"string"}},"required":["line1","city","region","postalCode","country"]},"supportEmail":{"type":"string","format":"email"},"supportUrl":{"type":["string","null"]},"supportPhone":{"type":["string","null"]}},"required":["legalName","taxIdType","taxId","address","supportEmail","supportUrl","supportPhone"],"description":"The seller identity and support channels disclosed when the buyer paid."},"contractSnapshot":{"type":["object","null"],"properties":{"contentTitle":{"type":"string"},"offerName":{"type":"string"},"amount":{"type":"integer"},"currency":{"type":"string"},"installmentAmounts":{"type":"array","items":{"type":"integer"}},"accessTerms":{"type":"string"},"withdrawalDays":{"type":"integer"},"termsVersion":{"type":"integer"}},"required":["contentTitle","offerName","amount","currency","installmentAmounts","accessTerms","withdrawalDays","termsVersion"],"description":"The course, offer, exact installment schedule and access terms accepted at checkout."}},"required":["platformFees","platformFeeBps","collectedAmount","platformFeeAmount","id","contentId","contentTitle","userId","buyerName","buyerEmail","learnerUserId","learnerName","learnerEmail","buyerLegalName","buyerTaxId","buyerTaxIdType","buyerCountry","amount","currency","status","installments","createdAt","refundedAt","withdrawalEligibleUntil","refundKind","refundStatus","refundRequestedAt","refundResolvedAt","refundReason","refundResolutionReason","refundedAmount","sellerSnapshot","contractSnapshot"]}},"page":{"type":"integer"},"pageSize":{"type":"integer"},"total":{"type":"integer"}},"required":["purchases","page","pageSize","total"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/payouts":{"get":{"tags":["Sales"],"operationId":"getPayouts","summary":"List connected-account payments","description":"Every provider-verified direct course payment on the organization's connected Stripe account, newest first. Installment plans produce one fact per paid invoice. No Cursare transfer is created. Amounts are in the currency's minor unit (cents).","parameters":[{"name":"limit","in":"query","schema":{"default":100,"type":"integer","minimum":1,"maximum":500}}],"responses":{"200":{"description":"List connected-account payments.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"payouts":{"type":"array","items":{"type":"object","properties":{"amount":{"type":"integer","description":"The direct connected-account payment, in minor units."},"currency":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"availableAt":{"type":"string","format":"date-time","description":"Scheduled provider balance availability after the protected payout delay."},"providerAccountReference":{"type":"string"},"providerPaymentReference":{"type":"string"}},"required":["amount","currency","createdAt","availableAt","providerAccountReference","providerPaymentReference"]}},"totals":{"type":"array","items":{"type":"object","properties":{"currency":{"type":"string"},"amount":{"type":"integer"}},"required":["currency","amount"]},"description":"Sums over the returned rows, grouped by currency."}},"required":["payouts","totals"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/affiliate-program":{"get":{"tags":["Affiliates"],"operationId":"getAffiliateProgram","summary":"Get the affiliate program settings","description":"SYSTEM — Cursare's NATIVE affiliate program: affiliates sign up on the org's own Cursare storefront, Cursare attributes the `?ref=` sale at checkout and holds the running balance the org owes them, and the org approves, blocks and settles people through these operations. This is the platform's only affiliate system; no external affiliate tracker is connected. The org's referral-program configuration: whether it accepts affiliates and the default commission every affiliate earns. Call this first — the roster's per-affiliate `commissionBps` is an override that is null whenever this default applies.","responses":{"200":{"description":"Get the affiliate program settings.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"mode":{"type":"string","enum":["off","open","approval"],"description":"`off` = no program, nobody can join and no `?ref` link earns; `open` = anyone who joins is active immediately; `approval` = joins land as `pending` until an admin approves them."},"commissionBps":{"type":"integer","minimum":0,"maximum":10000,"description":"The org-wide DEFAULT commission, in basis points. Applies to every affiliate without a negotiated override (an offer's own rate, when set, wins over this)."}},"required":["mode","commissionBps"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"tags":["Affiliates"],"operationId":"updateAffiliateProgram","summary":"Update the affiliate program settings","description":"SYSTEM — Cursare's NATIVE affiliate program: affiliates sign up on the org's own Cursare storefront, Cursare attributes the `?ref=` sale at checkout and holds the running balance the org owes them, and the org approves, blocks and settles people through these operations. This is the platform's only affiliate system; no external affiliate tracker is connected. Turn the referral program on or off and set the org-wide default commission. ORG-ADMIN only. Both fields are optional — send just the one you mean. FINANCIAL EFFECT: raising `commissionBps` raises what the org owes on every FUTURE attributed sale (already-recorded sales keep the rate frozen at their purchase time). Setting `mode` to `off` stops all new attribution immediately — existing `?ref` links stop earning — but does not erase the roster or any unpaid balance.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"mode":{"type":"string","enum":["off","open","approval"]},"commissionBps":{"type":"integer","minimum":0,"maximum":10000}}}}}},"responses":{"200":{"description":"Update the affiliate program settings.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"mode":{"type":"string","enum":["off","open","approval"],"description":"`off` = no program, nobody can join and no `?ref` link earns; `open` = anyone who joins is active immediately; `approval` = joins land as `pending` until an admin approves them."},"commissionBps":{"type":"integer","minimum":0,"maximum":10000,"description":"The org-wide DEFAULT commission, in basis points. Applies to every affiliate without a negotiated override (an offer's own rate, when set, wins over this)."}},"required":["mode","commissionBps"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/affiliates":{"get":{"tags":["Affiliates"],"operationId":"listAffiliates","summary":"List the affiliate roster","description":"SYSTEM — Cursare's NATIVE affiliate program: affiliates sign up on the org's own Cursare storefront, Cursare attributes the `?ref=` sale at checkout and holds the running balance the org owes them, and the org approves, blocks and settles people through these operations. This is the platform's only affiliate system; no external affiliate tracker is connected. Every affiliate of the org — newest first — with their referral code, status, negotiated rate, and per-currency earnings (pending, paid, reversed). ORG-ADMIN only. This is the source of the `id` needed by every other Affiliates operation, and the only way to see what the org still owes: `earnings[].pendingAmount` is the unpaid balance. Paying someone? Keep `snapshotAt` — it is the cutoff to hand back to `settleAffiliate` as `asOf` so only the sales behind the figure you paid get marked paid.","responses":{"200":{"description":"List the affiliate roster.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"affiliates":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The affiliate id — the `{id}` every write below takes."},"userId":{"description":"The Cursare user behind the affiliate. Null when they deleted their account.","type":["string","null"]},"name":{"type":["string","null"]},"email":{"type":["string","null"],"format":"email"},"image":{"description":"Avatar URL, if the user has one.","type":["string","null"]},"code":{"type":"string","description":"The public referral code — the `?ref=` value that attributes a sale to them."},"status":{"type":"string","enum":["pending","active","blocked"],"description":"`pending` = awaiting approval, earns nothing yet; `active` = their links attribute sales; `blocked` = removed from the program, future links stop attributing (history is kept)."},"commissionBps":{"type":["integer","null"],"minimum":0,"maximum":10000,"description":"The NEGOTIATED per-affiliate override in basis points. Null means the program default (see `getAffiliateProgram`) applies — read the effective rate as `commissionBps ?? program.commissionBps`."},"createdAt":{"type":"string","format":"date-time","description":"When they joined the program."},"earnings":{"type":"array","items":{"type":"object","properties":{"currency":{"type":"string","description":"ISO currency code, e.g. `BRL`."},"sales":{"type":"integer","description":"Attributed sales that still stand (not refunded, not canceled)."},"pendingAmount":{"type":"integer","description":"Commission owed and NOT yet settled, in the currency's minor unit (cents)."},"paidAmount":{"type":"integer","description":"Commission already marked paid by the org, in minor units."},"reversedAmount":{"type":"integer","description":"Already-paid commission whose sale was later refunded — the org overpaid by this much and typically offsets it on the next payout. In minor units."}},"required":["currency","sales","pendingAmount","paidAmount","reversedAmount"]},"description":"Money owed and handed over, one entry per currency. Empty until they drive a sale."}},"required":["id","userId","name","email","image","code","status","commissionBps","createdAt","earnings"]}},"snapshotAt":{"type":"string","format":"date-time","description":"The server-side instant these earnings were read at, from the DATABASE clock. Pass it verbatim as `settleAffiliate`'s `asOf` when you pay against this roster — it is the only trustworthy cutoff, since a client clock drifts from the clock that timestamps sales and would settle the wrong set. Any sale recorded after this instant stays pending, which is the safe direction."}},"required":["affiliates","snapshotAt"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/affiliates/{id}/approve":{"post":{"tags":["Affiliates"],"operationId":"approveAffiliate","summary":"Approve or unblock an affiliate","description":"SYSTEM — Cursare's NATIVE affiliate program: affiliates sign up on the org's own Cursare storefront, Cursare attributes the `?ref=` sale at checkout and holds the running balance the org owes them, and the org approves, blocks and settles people through these operations. This is the platform's only affiliate system; no external affiliate tracker is connected. Sets the affiliate to `active`, so their `?ref` links start attributing sales and earning commission. Use it both for a `pending` applicant (programs in `approval` mode) and to UNBLOCK someone previously blocked. ORG-ADMIN only. Idempotent — approving an already active affiliate changes nothing. Past sales are never re-attributed.","parameters":[{"name":"id","in":"path","required":true,"description":"The affiliate id, from `listAffiliates`.","schema":{"type":"string"}}],"responses":{"200":{"description":"Approve or unblock an affiliate.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","const":"active"}},"required":["id","status"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/affiliates/{id}/block":{"post":{"tags":["Affiliates"],"operationId":"blockAffiliate","summary":"Block an affiliate","description":"SYSTEM — Cursare's NATIVE affiliate program: affiliates sign up on the org's own Cursare storefront, Cursare attributes the `?ref=` sale at checkout and holds the running balance the org owes them, and the org approves, blocks and settles people through these operations. This is the platform's only affiliate system; no external affiliate tracker is connected. Sets the affiliate to `blocked`: their `?ref` links stop attributing NEW sales immediately. History is kept — already-attributed sales and any unpaid balance survive, so settle up (`settleAffiliate`) before or after blocking if you still owe them. ORG-ADMIN only. Reversible with `approveAffiliate`.","parameters":[{"name":"id","in":"path","required":true,"description":"The affiliate id, from `listAffiliates`.","schema":{"type":"string"}}],"responses":{"200":{"description":"Block an affiliate.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","const":"blocked"}},"required":["id","status"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/affiliates/{id}/commission":{"put":{"tags":["Affiliates"],"operationId":"setAffiliateCommission","summary":"Set or clear an affiliate's negotiated commission","description":"SYSTEM — Cursare's NATIVE affiliate program: affiliates sign up on the org's own Cursare storefront, Cursare attributes the `?ref=` sale at checkout and holds the running balance the org owes them, and the org approves, blocks and settles people through these operations. This is the platform's only affiliate system; no external affiliate tracker is connected. Overrides the program default for ONE affiliate. ORG-ADMIN only. FINANCIAL EFFECT: this rate is what FUTURE attributed sales will owe this person — sales already recorded keep the rate frozen onto them and are not recalculated. Send `{\"commissionBps\": null}` to REMOVE the override and fall back to the program default from `getAffiliateProgram`. The value is in basis points, not percent.","parameters":[{"name":"id","in":"path","required":true,"description":"The affiliate id, from `listAffiliates`.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"commissionBps":{"type":["integer","null"],"minimum":0,"maximum":10000}},"required":["commissionBps"]}}}},"responses":{"200":{"description":"Set or clear an affiliate's negotiated commission.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"commissionBps":{"type":["integer","null"],"description":"The stored override after the write — null means the program default applies."}},"required":["id","commissionBps"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/affiliates/{id}/settle":{"post":{"tags":["Affiliates"],"operationId":"settleAffiliate","summary":"Mark an affiliate's outstanding commissions as paid","description":"SYSTEM — Cursare's NATIVE affiliate program: affiliates sign up on the org's own Cursare storefront, Cursare attributes the `?ref=` sale at checkout and holds the running balance the org owes them, and the org approves, blocks and settles people through these operations. This is the platform's only affiliate system; no external affiliate tracker is connected. Records a payout: every unsettled commission of this affiliate is MARKED PAID and its `pendingAmount` drops to zero. ORG-ADMIN only. IRREVERSIBLE — there is no unsettle operation, and a wrong call makes the org's books claim money was handed over when it was not. This only BOOKKEEPS: Cursare moves no money, the org pays the affiliate outside the platform (transfer, Pix, etc.). Only call it after the payment has actually been sent. Refunded and canceled sales are skipped. `asOf` bounds the stamp to sales recorded at or before that instant, so a sale landing between the moment you read the pending figure and this call is NOT silently marked paid: call `listAffiliates`, pay the `pendingAmount` you read there, then send that same response's `snapshotAt` back here as `asOf`. Never invent the value from a local clock — it drifts from the clock that timestamps sales. Omitting it settles everything outstanding right now, which also settles anything that landed while you were paying.","parameters":[{"name":"id","in":"path","required":true,"description":"The affiliate id, from `listAffiliates`.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"asOf":{"type":"string","format":"date-time","description":"Only settle commissions from sales recorded at or before this ISO date-time. Use the `snapshotAt` returned by the `listAffiliates` call whose `pendingAmount` you actually paid — not a client-generated timestamp. Defaults to now (the database clock)."}}}}}},"responses":{"200":{"description":"Mark an affiliate's outstanding commissions as paid.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"asOf":{"type":"string","format":"date-time","description":"The cutoff actually applied — echoed back so the payout can be reconciled."},"settled":{"type":"array","items":{"type":"object","properties":{"currency":{"type":"string","description":"ISO currency code."},"amount":{"type":"integer","description":"Total commission marked paid in this currency, in minor units (cents)."}},"required":["currency","amount"]},"description":"What this call marked paid, per currency. Empty when nothing was outstanding."}},"required":["id","asOf","settled"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/tracked-links":{"get":{"tags":["Links"],"operationId":"listTrackedLinks","summary":"List links","description":"Lists the organization's first-party short links. Click metrics use pseudonymous server-side counts with bot filtering and hourly deduplication; purchases, learners and revenue come from authoritative business records.","parameters":[{"name":"q","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"default":"all","type":"string","enum":["all","active","archived"]}},{"name":"sort","in":"query","schema":{"default":"newest","type":"string","enum":["newest","oldest","label"]}},{"name":"page","in":"query","schema":{"default":1,"type":"integer","minimum":1}},{"name":"pageSize","in":"query","schema":{"default":25,"type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"description":"List links.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"links":{"type":"array","items":{"type":"object","properties":{"preview":{"type":["object","null"],"properties":{"title":{"description":"Custom public sharing title; blank uses the published course title.","type":"string","maxLength":160},"description":{"description":"Custom public sharing description; blank uses the published course description.","type":"string","maxLength":500},"image":{"description":"Public HTTPS image URL; blank uses the course image or site fallback.","type":"string","maxLength":2048}}},"id":{"type":"string"},"organizationId":{"type":"string"},"slug":{"type":"string","description":"The organization-unique segment used in `/l/{slug}`."},"label":{"type":"string"},"destination":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"content"},"contentId":{"type":"string","minLength":1,"description":"An offered, published content in this organization."},"offerId":{"description":"An active offer belonging to this content and organization. Redirects preserve this exact offer through the course enrollment flow.","type":"string","minLength":1}},"required":["kind","contentId"]},{"type":"object","properties":{"kind":{"type":"string","const":"external"},"url":{"type":"string","format":"uri","description":"A credential-free HTTPS destination outside Cursare."}},"required":["kind","url"]}]},"experiment":{"type":["object","null"],"properties":{"status":{"type":"string","enum":["running","completed"]},"startedAt":{"type":"string","format":"date-time"},"endedAt":{"type":["string","null"],"format":"date-time"},"winner":{"type":["string","null"],"enum":["A","B"]},"variants":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","enum":["A","B"]},"percentage":{"type":"integer"},"destination":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"content"},"contentId":{"type":"string","minLength":1,"description":"An offered, published content in this organization."},"offerId":{"description":"An active offer belonging to this content and organization. Redirects preserve this exact offer through the course enrollment flow.","type":"string","minLength":1}},"required":["kind","contentId"]},{"type":"object","properties":{"kind":{"type":"string","const":"external"},"url":{"type":"string","format":"uri","description":"A credential-free HTTPS destination outside Cursare."}},"required":["kind","url"]}]}},"required":["id","name","percentage","destination"]}}},"required":["status","startedAt","endedAt","winner","variants"],"description":"An immutable A/B experiment. Internal variant IDs carry attribution through visits, checkout and enrollment."},"affiliateId":{"type":["string","null"]},"affiliateCode":{"type":["string","null"]},"utm":{"type":"object","properties":{"source":{"type":"string","maxLength":100},"medium":{"type":"string","maxLength":100},"campaign":{"type":"string","maxLength":100},"content":{"type":"string","maxLength":100},"term":{"type":"string","maxLength":100}}},"archivedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["preview","id","organizationId","slug","label","destination","experiment","affiliateId","affiliateCode","utm","archivedAt","createdAt","updatedAt"]}},"page":{"type":"integer"},"pageSize":{"type":"integer"},"total":{"type":"integer"},"hasMore":{"type":"boolean"}},"required":["links","page","pageSize","total","hasMore"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"tags":["Links"],"operationId":"createTrackedLink","summary":"Create a link","description":"Creates a first-party `/l/{slug}` link to an offered course or a guarded HTTPS URL. A generated slug is used when omitted.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"preview":{"type":"object","properties":{"title":{"description":"Custom public sharing title; blank uses the published course title.","type":"string","maxLength":160},"description":{"description":"Custom public sharing description; blank uses the published course description.","type":"string","maxLength":500},"image":{"description":"Public HTTPS image URL; blank uses the course image or site fallback.","type":"string","maxLength":2048}}},"label":{"type":"string","minLength":1,"maxLength":120},"destination":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"content"},"contentId":{"type":"string","minLength":1,"description":"An offered, published content in this organization."},"offerId":{"description":"An active offer belonging to this content and organization. Redirects preserve this exact offer through the course enrollment flow.","type":"string","minLength":1}},"required":["kind","contentId"]},{"type":"object","properties":{"kind":{"type":"string","const":"external"},"url":{"type":"string","format":"uri","description":"A credential-free HTTPS destination outside Cursare."}},"required":["kind","url"]}]},"affiliateId":{"type":["string","null"]},"utm":{"type":"object","properties":{"source":{"type":"string","maxLength":100},"medium":{"type":"string","maxLength":100},"campaign":{"type":"string","maxLength":100},"content":{"type":"string","maxLength":100},"term":{"type":"string","maxLength":100}}},"slug":{"type":"string","minLength":3,"maxLength":64}},"required":["label","destination"]}}}},"responses":{"201":{"description":"Create a link.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"preview":{"type":["object","null"],"properties":{"title":{"description":"Custom public sharing title; blank uses the published course title.","type":"string","maxLength":160},"description":{"description":"Custom public sharing description; blank uses the published course description.","type":"string","maxLength":500},"image":{"description":"Public HTTPS image URL; blank uses the course image or site fallback.","type":"string","maxLength":2048}}},"id":{"type":"string"},"organizationId":{"type":"string"},"slug":{"type":"string","description":"The organization-unique segment used in `/l/{slug}`."},"label":{"type":"string"},"destination":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"content"},"contentId":{"type":"string","minLength":1,"description":"An offered, published content in this organization."},"offerId":{"description":"An active offer belonging to this content and organization. Redirects preserve this exact offer through the course enrollment flow.","type":"string","minLength":1}},"required":["kind","contentId"]},{"type":"object","properties":{"kind":{"type":"string","const":"external"},"url":{"type":"string","format":"uri","description":"A credential-free HTTPS destination outside Cursare."}},"required":["kind","url"]}]},"experiment":{"type":["object","null"],"properties":{"status":{"type":"string","enum":["running","completed"]},"startedAt":{"type":"string","format":"date-time"},"endedAt":{"type":["string","null"],"format":"date-time"},"winner":{"type":["string","null"],"enum":["A","B"]},"variants":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","enum":["A","B"]},"percentage":{"type":"integer"},"destination":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"content"},"contentId":{"type":"string","minLength":1,"description":"An offered, published content in this organization."},"offerId":{"description":"An active offer belonging to this content and organization. Redirects preserve this exact offer through the course enrollment flow.","type":"string","minLength":1}},"required":["kind","contentId"]},{"type":"object","properties":{"kind":{"type":"string","const":"external"},"url":{"type":"string","format":"uri","description":"A credential-free HTTPS destination outside Cursare."}},"required":["kind","url"]}]}},"required":["id","name","percentage","destination"]}}},"required":["status","startedAt","endedAt","winner","variants"],"description":"An immutable A/B experiment. Internal variant IDs carry attribution through visits, checkout and enrollment."},"affiliateId":{"type":["string","null"]},"affiliateCode":{"type":["string","null"]},"utm":{"type":"object","properties":{"source":{"type":"string","maxLength":100},"medium":{"type":"string","maxLength":100},"campaign":{"type":"string","maxLength":100},"content":{"type":"string","maxLength":100},"term":{"type":"string","maxLength":100}}},"archivedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["preview","id","organizationId","slug","label","destination","experiment","affiliateId","affiliateCode","utm","archivedAt","createdAt","updatedAt"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/tracked-links/{id}":{"get":{"tags":["Links"],"operationId":"getTrackedLink","summary":"Get a link","parameters":[{"name":"id","in":"path","required":true,"description":"The tracked-link id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Get a link.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"preview":{"type":["object","null"],"properties":{"title":{"description":"Custom public sharing title; blank uses the published course title.","type":"string","maxLength":160},"description":{"description":"Custom public sharing description; blank uses the published course description.","type":"string","maxLength":500},"image":{"description":"Public HTTPS image URL; blank uses the course image or site fallback.","type":"string","maxLength":2048}}},"id":{"type":"string"},"organizationId":{"type":"string"},"slug":{"type":"string","description":"The organization-unique segment used in `/l/{slug}`."},"label":{"type":"string"},"destination":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"content"},"contentId":{"type":"string","minLength":1,"description":"An offered, published content in this organization."},"offerId":{"description":"An active offer belonging to this content and organization. Redirects preserve this exact offer through the course enrollment flow.","type":"string","minLength":1}},"required":["kind","contentId"]},{"type":"object","properties":{"kind":{"type":"string","const":"external"},"url":{"type":"string","format":"uri","description":"A credential-free HTTPS destination outside Cursare."}},"required":["kind","url"]}]},"experiment":{"type":["object","null"],"properties":{"status":{"type":"string","enum":["running","completed"]},"startedAt":{"type":"string","format":"date-time"},"endedAt":{"type":["string","null"],"format":"date-time"},"winner":{"type":["string","null"],"enum":["A","B"]},"variants":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","enum":["A","B"]},"percentage":{"type":"integer"},"destination":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"content"},"contentId":{"type":"string","minLength":1,"description":"An offered, published content in this organization."},"offerId":{"description":"An active offer belonging to this content and organization. Redirects preserve this exact offer through the course enrollment flow.","type":"string","minLength":1}},"required":["kind","contentId"]},{"type":"object","properties":{"kind":{"type":"string","const":"external"},"url":{"type":"string","format":"uri","description":"A credential-free HTTPS destination outside Cursare."}},"required":["kind","url"]}]}},"required":["id","name","percentage","destination"]}}},"required":["status","startedAt","endedAt","winner","variants"],"description":"An immutable A/B experiment. Internal variant IDs carry attribution through visits, checkout and enrollment."},"affiliateId":{"type":["string","null"]},"affiliateCode":{"type":["string","null"]},"utm":{"type":"object","properties":{"source":{"type":"string","maxLength":100},"medium":{"type":"string","maxLength":100},"campaign":{"type":"string","maxLength":100},"content":{"type":"string","maxLength":100},"term":{"type":"string","maxLength":100}}},"archivedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["preview","id","organizationId","slug","label","destination","experiment","affiliateId","affiliateCode","utm","archivedAt","createdAt","updatedAt"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"tags":["Links"],"operationId":"updateTrackedLink","summary":"Update a link","description":"Updates an active link without changing its stable short slug. Archived links are immutable.","parameters":[{"name":"id","in":"path","required":true,"description":"The tracked-link id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"preview":{"type":"object","properties":{"title":{"description":"Custom public sharing title; blank uses the published course title.","type":"string","maxLength":160},"description":{"description":"Custom public sharing description; blank uses the published course description.","type":"string","maxLength":500},"image":{"description":"Public HTTPS image URL; blank uses the course image or site fallback.","type":"string","maxLength":2048}}},"label":{"type":"string","minLength":1,"maxLength":120},"destination":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"content"},"contentId":{"type":"string","minLength":1,"description":"An offered, published content in this organization."},"offerId":{"description":"An active offer belonging to this content and organization. Redirects preserve this exact offer through the course enrollment flow.","type":"string","minLength":1}},"required":["kind","contentId"]},{"type":"object","properties":{"kind":{"type":"string","const":"external"},"url":{"type":"string","format":"uri","description":"A credential-free HTTPS destination outside Cursare."}},"required":["kind","url"]}]},"affiliateId":{"type":["string","null"]},"utm":{"type":"object","properties":{"source":{"type":"string","maxLength":100},"medium":{"type":"string","maxLength":100},"campaign":{"type":"string","maxLength":100},"content":{"type":"string","maxLength":100},"term":{"type":"string","maxLength":100}}},"experiment":{"description":"Start or finish an experiment. Send this field alone. Each link supports one experiment; create a new link to test again.","anyOf":[{"type":"object","properties":{"destinationB":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"content"},"contentId":{"type":"string","minLength":1,"description":"An offered, published content in this organization."},"offerId":{"description":"An active offer belonging to this content and organization. Redirects preserve this exact offer through the course enrollment flow.","type":"string","minLength":1}},"required":["kind","contentId"]},{"type":"object","properties":{"kind":{"type":"string","const":"external"},"url":{"type":"string","format":"uri","description":"A credential-free HTTPS destination outside Cursare."}},"required":["kind","url"]}]},"percentageA":{"type":"integer","minimum":1,"maximum":99,"description":"Share of traffic for the current destination (A); B receives the remainder. Fixed after starting."}},"required":["destinationB","percentageA"]},{"type":"object","properties":{"winner":{"type":"string","enum":["A","B"],"description":"Finish the running experiment and send future traffic to this destination."}},"required":["winner"]}]}}}}}},"responses":{"200":{"description":"Update a link.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"preview":{"type":["object","null"],"properties":{"title":{"description":"Custom public sharing title; blank uses the published course title.","type":"string","maxLength":160},"description":{"description":"Custom public sharing description; blank uses the published course description.","type":"string","maxLength":500},"image":{"description":"Public HTTPS image URL; blank uses the course image or site fallback.","type":"string","maxLength":2048}}},"id":{"type":"string"},"organizationId":{"type":"string"},"slug":{"type":"string","description":"The organization-unique segment used in `/l/{slug}`."},"label":{"type":"string"},"destination":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"content"},"contentId":{"type":"string","minLength":1,"description":"An offered, published content in this organization."},"offerId":{"description":"An active offer belonging to this content and organization. Redirects preserve this exact offer through the course enrollment flow.","type":"string","minLength":1}},"required":["kind","contentId"]},{"type":"object","properties":{"kind":{"type":"string","const":"external"},"url":{"type":"string","format":"uri","description":"A credential-free HTTPS destination outside Cursare."}},"required":["kind","url"]}]},"experiment":{"type":["object","null"],"properties":{"status":{"type":"string","enum":["running","completed"]},"startedAt":{"type":"string","format":"date-time"},"endedAt":{"type":["string","null"],"format":"date-time"},"winner":{"type":["string","null"],"enum":["A","B"]},"variants":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","enum":["A","B"]},"percentage":{"type":"integer"},"destination":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"content"},"contentId":{"type":"string","minLength":1,"description":"An offered, published content in this organization."},"offerId":{"description":"An active offer belonging to this content and organization. Redirects preserve this exact offer through the course enrollment flow.","type":"string","minLength":1}},"required":["kind","contentId"]},{"type":"object","properties":{"kind":{"type":"string","const":"external"},"url":{"type":"string","format":"uri","description":"A credential-free HTTPS destination outside Cursare."}},"required":["kind","url"]}]}},"required":["id","name","percentage","destination"]}}},"required":["status","startedAt","endedAt","winner","variants"],"description":"An immutable A/B experiment. Internal variant IDs carry attribution through visits, checkout and enrollment."},"affiliateId":{"type":["string","null"]},"affiliateCode":{"type":["string","null"]},"utm":{"type":"object","properties":{"source":{"type":"string","maxLength":100},"medium":{"type":"string","maxLength":100},"campaign":{"type":"string","maxLength":100},"content":{"type":"string","maxLength":100},"term":{"type":"string","maxLength":100}}},"archivedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["preview","id","organizationId","slug","label","destination","experiment","affiliateId","affiliateCode","utm","archivedAt","createdAt","updatedAt"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"tags":["Links"],"operationId":"archiveTrackedLink","summary":"Archive a link","description":"Stops future redirects while retaining historical attribution, conversions and reports. Idempotent.","parameters":[{"name":"id","in":"path","required":true,"description":"The tracked-link id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Archive a link.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"preview":{"type":["object","null"],"properties":{"title":{"description":"Custom public sharing title; blank uses the published course title.","type":"string","maxLength":160},"description":{"description":"Custom public sharing description; blank uses the published course description.","type":"string","maxLength":500},"image":{"description":"Public HTTPS image URL; blank uses the course image or site fallback.","type":"string","maxLength":2048}}},"id":{"type":"string"},"organizationId":{"type":"string"},"slug":{"type":"string","description":"The organization-unique segment used in `/l/{slug}`."},"label":{"type":"string"},"destination":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"content"},"contentId":{"type":"string","minLength":1,"description":"An offered, published content in this organization."},"offerId":{"description":"An active offer belonging to this content and organization. Redirects preserve this exact offer through the course enrollment flow.","type":"string","minLength":1}},"required":["kind","contentId"]},{"type":"object","properties":{"kind":{"type":"string","const":"external"},"url":{"type":"string","format":"uri","description":"A credential-free HTTPS destination outside Cursare."}},"required":["kind","url"]}]},"experiment":{"type":["object","null"],"properties":{"status":{"type":"string","enum":["running","completed"]},"startedAt":{"type":"string","format":"date-time"},"endedAt":{"type":["string","null"],"format":"date-time"},"winner":{"type":["string","null"],"enum":["A","B"]},"variants":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","enum":["A","B"]},"percentage":{"type":"integer"},"destination":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"content"},"contentId":{"type":"string","minLength":1,"description":"An offered, published content in this organization."},"offerId":{"description":"An active offer belonging to this content and organization. Redirects preserve this exact offer through the course enrollment flow.","type":"string","minLength":1}},"required":["kind","contentId"]},{"type":"object","properties":{"kind":{"type":"string","const":"external"},"url":{"type":"string","format":"uri","description":"A credential-free HTTPS destination outside Cursare."}},"required":["kind","url"]}]}},"required":["id","name","percentage","destination"]}}},"required":["status","startedAt","endedAt","winner","variants"],"description":"An immutable A/B experiment. Internal variant IDs carry attribution through visits, checkout and enrollment."},"affiliateId":{"type":["string","null"]},"affiliateCode":{"type":["string","null"]},"utm":{"type":"object","properties":{"source":{"type":"string","maxLength":100},"medium":{"type":"string","maxLength":100},"campaign":{"type":"string","maxLength":100},"content":{"type":"string","maxLength":100},"term":{"type":"string","maxLength":100}}},"archivedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["preview","id","organizationId","slug","label","destination","experiment","affiliateId","affiliateCode","utm","archivedAt","createdAt","updatedAt"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/tracked-links/{id}/permanent":{"delete":{"tags":["Links"],"operationId":"deleteTrackedLink","summary":"Permanently delete a link","description":"Permanently removes the link and its A/B variants. Existing purchases and enrollments remain, but their link attribution is cleared. Unlike archiving, this operation cannot be undone.","parameters":[{"name":"id","in":"path","required":true,"description":"The tracked-link id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Permanently delete a link.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"deleted":{"type":"boolean","const":true}},"required":["deleted"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/tracked-links/{id}/insights":{"get":{"tags":["Links"],"operationId":"getTrackedLinkInsights","summary":"Get tracked-link funnel insights","description":"Returns server-side clicks and estimated unique visitors plus authoritative checkout, purchase, learner and currency-separated revenue totals for a bounded window of at most 366 days.","parameters":[{"name":"id","in":"path","required":true,"description":"The tracked-link id.","schema":{"type":"string"}},{"name":"since","in":"query","required":true,"schema":{"type":"string","format":"date-time"}},{"name":"until","in":"query","required":true,"schema":{"type":"string","format":"date-time"}},{"name":"variant","in":"query","description":"Filter to one experiment variant; omitted totals include both variants and traffic outside the experiment.","schema":{"type":"string","enum":["A","B"]}}],"responses":{"200":{"description":"Get tracked-link funnel insights.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"visits":{"type":"integer"},"uniqueVisitors":{"type":"integer"},"requests":{"type":"integer","description":"Enrollment requests created in the period, including requests later approved or rejected."},"checkoutStarts":{"type":"integer"},"purchases":{"type":"integer"},"learners":{"type":"integer"},"revenue":{"type":"array","items":{"type":"object","properties":{"currency":{"type":"string"},"gross":{"type":"integer","description":"Gross sales in the currency's minor unit."},"refunded":{"type":"integer","description":"Refunded amount in the currency's minor unit."},"net":{"type":"integer","description":"Gross minus refunded amount in the currency's minor unit."}},"required":["currency","gross","refunded","net"]}}},"required":["visits","uniqueVisitors","requests","checkoutStarts","purchases","learners","revenue"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/contents/{id}/reviews":{"get":{"tags":["Reviews"],"operationId":"listContentReviews","summary":"List a content's reviews","description":"The content's rating summary plus its most recent reviews. Reviews are learner-authored on the course page — this endpoint is read-only.","parameters":[{"name":"id","in":"path","required":true,"description":"The content id.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"Maximum reviews to return (newest first).","schema":{"default":20,"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"List a content's reviews.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"summary":{"type":"object","properties":{"average":{"type":"number","description":"Mean rating, 0 when there are no reviews."},"count":{"type":"integer"}},"required":["average","count"]},"reviews":{"type":"array","items":{"type":"object","properties":{"rating":{"type":"integer","minimum":1,"maximum":5},"comment":{"type":["string","null"]},"reviewerName":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}},"required":["rating","comment","reviewerName","createdAt"]}}},"required":["summary","reviews"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/insights/health":{"get":{"tags":["Insights"],"operationId":"getAnalyticsHealth","summary":"Analytics collection health","description":"Returns bounded operational counters for accepted and rejected browser events, server-delivery retries and terminal failures, GA4 freshness, tracked-purchase coverage, and the Google/Cursare purchase discrepancy. Rejected payload content is never retained.","parameters":[{"name":"from","in":"query","description":"Inclusive UTC start. Defaults to 29 days before `to`. Maximum 366 days.","schema":{"type":"string","format":"date"}},{"name":"to","in":"query","description":"Inclusive UTC end. Defaults to today.","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Analytics collection health.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"from":{"type":"string","format":"date"},"to":{"type":"string","format":"date"},"generatedAt":{"type":"string","format":"date-time"},"collection":{"type":"object","properties":{"accepted":{"type":"integer","minimum":0},"issues":{"type":"object","properties":{"invalid_payload":{"type":"integer","minimum":0},"timestamp_outside_window":{"type":"integer","minimum":0},"invalid_scope":{"type":"integer","minimum":0},"rate_limited":{"type":"integer","minimum":0}},"required":["invalid_payload","timestamp_outside_window","invalid_scope","rate_limited"]}},"required":["accepted","issues"]},"delivery":{"type":"object","properties":{"pending":{"type":"integer","minimum":0},"succeeded":{"type":"integer","minimum":0},"suppressed":{"type":"integer","minimum":0},"retrying":{"type":"integer","minimum":0},"terminal":{"type":"integer","minimum":0},"dead":{"type":"integer","minimum":0}},"required":["pending","succeeded","suppressed","retrying","terminal","dead"]},"coverage":{"type":"object","properties":{"cursarePurchases":{"type":"integer","minimum":0},"trackedPurchaseCoverage":{"type":["number","null"],"minimum":0,"description":"Percentage, or null when the declared denominator is zero."},"googleObservedPurchases":{"type":["number","null"],"minimum":0},"purchaseDiscrepancy":{"type":["number","null"]}},"required":["cursarePurchases","trackedPurchaseCoverage","googleObservedPurchases","purchaseDiscrepancy"]},"google":{"type":"object","properties":{"health":{"type":"string","enum":["current","delayed","unavailable","not_connected"]},"freshThrough":{"type":["string","null"],"format":"date-time"},"generatedAt":{"type":"string","format":"date-time"},"reportAgeSeconds":{"type":"integer","minimum":0},"issueCode":{"type":["string","null"],"enum":["authorization_revoked","insufficient_scope","resource_unavailable","provider_unavailable"]}},"required":["health","freshThrough","generatedAt","reportAgeSeconds","issueCode"]}},"required":["from","to","generatedAt","collection","delivery","coverage","google"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/insights/google":{"get":{"tags":["Insights"],"operationId":"getGoogleInsights","summary":"Source-labeled Google Analytics context","description":"Returns one bounded report from the fixed Cursare GA4 catalog. Google users, sessions, acquisition dimensions, and observed funnel events augment—but never replace or merge with—authoritative Cursare financial and academic facts.","parameters":[{"name":"report","in":"query","required":true,"description":"A fixed report shape; arbitrary Google dimensions and metrics are not accepted.","schema":{"type":"string","enum":["overview","source_medium","campaign","landing_page","device","geography","funnel"]}},{"name":"from","in":"query","description":"Inclusive UTC start. Defaults to 29 days before `to`. Maximum 366 days.","schema":{"type":"string","format":"date"}},{"name":"to","in":"query","description":"Inclusive UTC end. Defaults to today.","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Source-labeled Google Analytics context.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"metadata":{"type":"object","properties":{"source":{"type":"string","const":"google"},"reportVersion":{"type":"number","const":1},"from":{"type":"string","format":"date"},"to":{"type":"string","format":"date"},"generatedAt":{"type":"string","format":"date-time"},"freshThrough":{"type":["string","null"],"format":"date-time"},"health":{"type":"string","enum":["current","delayed","unavailable","not_connected"]}},"required":["source","reportVersion","from","to","generatedAt","freshThrough","health"]},"report":{"type":"string","enum":["overview","source_medium","campaign","landing_page","device","geography","funnel"]},"property":{"type":["object","null"],"properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]},"rows":{"type":"array","items":{"type":"object","properties":{"dimensions":{"type":"object","additionalProperties":{"type":"string"}},"metrics":{"type":"object","additionalProperties":{"type":"number"}}},"required":["dimensions","metrics"]}},"totalRows":{"type":"integer","minimum":0},"truncated":{"type":"boolean"}},"required":["metadata","report","property","rows","totalRows","truncated"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/insights/commerce":{"get":{"tags":["Insights"],"operationId":"getCommerceInsights","summary":"Authoritative commerce funnel insights","description":"Returns Cursare checkout, purchase, refund, revenue, conversion, abandonment, recovery, offer, campaign, and daily metrics. Monetary values remain separated by ISO currency and use minor units. Provider-confirmed expiration defines abandonment; browser cancellation does not.","parameters":[{"name":"from","in":"query","description":"Inclusive UTC start. Defaults to 29 days before `to`. Maximum 366 days.","schema":{"type":"string","format":"date"}},{"name":"to","in":"query","description":"Inclusive UTC end. Defaults to today.","schema":{"type":"string","format":"date"}},{"name":"contentId","in":"query","description":"Limit results to one content in this organization.","schema":{"type":"string"}},{"name":"offerId","in":"query","description":"Limit results to one offer.","schema":{"type":"string"}},{"name":"campaignId","in":"query","description":"Limit results to one campaign.","schema":{"type":"string"}},{"name":"cohortId","in":"query","description":"Limit academic results to one cohort.","schema":{"type":"string"}}],"responses":{"200":{"description":"Authoritative commerce funnel insights.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"metadata":{"type":"object","properties":{"source":{"type":"string","const":"cursare","description":"Authoritative Cursare operational and event facts."},"metricVersion":{"type":"number","const":1,"description":"Version of the published metric definitions."},"from":{"type":"string","format":"date","description":"Resolved inclusive UTC window start."},"to":{"type":"string","format":"date","description":"Resolved inclusive UTC window end."},"generatedAt":{"type":"string","format":"date-time","description":"When this response was generated."},"freshThrough":{"type":"string","format":"date-time","description":"Latest boundary represented by the source."},"health":{"type":"string","enum":["current","partial"],"description":"Partial means consented interaction coverage is not yet available."}},"required":["source","metricVersion","from","to","generatedAt","freshThrough","health"]},"funnel":{"type":"object","properties":{"views":{"type":"integer","description":"Consented course detail views."},"offerSelections":{"type":"integer","description":"Consented offer selections."},"campaignSelections":{"type":"integer","description":"Consented promotion selections."},"checkoutAttempts":{"type":"integer","description":"Started checkouts plus provider-creation failures."},"checkoutsStarted":{"type":"integer","description":"Provider checkouts successfully created."},"checkoutFailures":{"type":"integer","description":"Creation and delayed-payment failures, retained as separate fields below."},"checkoutCreationFailures":{"type":"integer","description":"Checkout attempts rejected before a provider checkout existed."},"delayedPaymentFailures":{"type":"integer","description":"Provider checkouts whose delayed payment later failed."},"checkoutsExpired":{"type":"integer","description":"Provider-confirmed expired unpaid checkouts."},"checkoutsRecovered":{"type":"integer","description":"Attempts explicitly resumed or replaced."},"purchases":{"type":"integer","description":"Authoritative completed purchases."},"refunds":{"type":"integer","description":"Authoritative refunds confirmed in the window."}},"required":["views","offerSelections","campaignSelections","checkoutAttempts","checkoutsStarted","checkoutFailures","checkoutCreationFailures","delayedPaymentFailures","checkoutsExpired","checkoutsRecovered","purchases","refunds"]},"rates":{"type":"object","properties":{"viewToCheckout":{"type":["number","null"],"minimum":0,"description":"Percentage, or null when the declared denominator is zero."},"checkoutFailure":{"type":["number","null"],"minimum":0,"description":"Percentage, or null when the declared denominator is zero."},"checkoutConversion":{"type":["number","null"],"minimum":0,"description":"Percentage, or null when the declared denominator is zero."},"checkoutAbandonment":{"type":["number","null"],"minimum":0,"description":"Percentage, or null when the declared denominator is zero."},"checkoutRecovery":{"type":["number","null"],"minimum":0,"description":"Percentage, or null when the declared denominator is zero."},"refund":{"type":["number","null"],"minimum":0,"description":"Percentage, or null when the declared denominator is zero."},"trackedPurchaseCoverage":{"type":["number","null"],"minimum":0,"description":"Authoritative purchases successfully delivered to Google divided by Cursare purchases."}},"required":["viewToCheckout","checkoutFailure","checkoutConversion","checkoutAbandonment","checkoutRecovery","refund","trackedPurchaseCoverage"]},"currencies":{"type":"array","items":{"type":"object","properties":{"currency":{"type":"string","minLength":3,"maxLength":3},"grossRevenue":{"type":"integer","description":"Completed purchase value in minor units."},"refundedRevenue":{"type":"integer","description":"Confirmed refund value in minor units."},"netRevenue":{"type":"integer","description":"Gross minus refunds in minor units."},"averagePaidValue":{"type":["integer","null"],"description":"Net value per paid purchase."},"purchases":{"type":"integer"},"refunds":{"type":"integer"}},"required":["currency","grossRevenue","refundedRevenue","netRevenue","averagePaidValue","purchases","refunds"]}},"breakdowns":{"type":"array","items":{"type":"object","properties":{"offerId":{"type":"string"},"campaignId":{"type":["string","null"]},"currency":{"type":"string","minLength":3,"maxLength":3},"purchases":{"type":"integer"},"revenue":{"type":"integer","description":"Non-refunded revenue in minor units."}},"required":["offerId","campaignId","currency","purchases","revenue"]}},"daily":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","format":"date"},"views":{"type":"integer"},"checkoutsStarted":{"type":"integer"},"purchases":{"type":"integer"},"refunds":{"type":"integer"},"revenueByCurrency":{"type":"object","propertyNames":{"type":"string","minLength":3,"maxLength":3},"additionalProperties":{"type":"integer"}}},"required":["date","views","checkoutsStarted","purchases","refunds","revenueByCurrency"]}}},"required":["metadata","funnel","rates","currencies","breakdowns","daily"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/insights/academic":{"get":{"tags":["Insights"],"operationId":"getAcademicInsights","summary":"Authoritative academic engagement insights","description":"Returns enrollment, activation, completion, quiz, video, certificate, and review metrics from Cursare facts. Start and video interactions are consented and therefore may be partial; completion and quiz facts remain authoritative.","parameters":[{"name":"from","in":"query","description":"Inclusive UTC start. Defaults to 29 days before `to`. Maximum 366 days.","schema":{"type":"string","format":"date"}},{"name":"to","in":"query","description":"Inclusive UTC end. Defaults to today.","schema":{"type":"string","format":"date"}},{"name":"contentId","in":"query","description":"Limit results to one content in this organization.","schema":{"type":"string"}},{"name":"offerId","in":"query","description":"Limit results to one offer.","schema":{"type":"string"}},{"name":"campaignId","in":"query","description":"Limit results to one campaign.","schema":{"type":"string"}},{"name":"cohortId","in":"query","description":"Limit academic results to one cohort.","schema":{"type":"string"}}],"responses":{"200":{"description":"Authoritative academic engagement insights.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"metadata":{"type":"object","properties":{"source":{"type":"string","const":"cursare","description":"Authoritative Cursare operational and event facts."},"metricVersion":{"type":"number","const":1,"description":"Version of the published metric definitions."},"from":{"type":"string","format":"date","description":"Resolved inclusive UTC window start."},"to":{"type":"string","format":"date","description":"Resolved inclusive UTC window end."},"generatedAt":{"type":"string","format":"date-time","description":"When this response was generated."},"freshThrough":{"type":"string","format":"date-time","description":"Latest boundary represented by the source."},"health":{"type":"string","enum":["current","partial"],"description":"Partial means consented interaction coverage is not yet available."}},"required":["source","metricVersion","from","to","generatedAt","freshThrough","health"]},"totals":{"type":"object","properties":{"enrollments":{"type":"integer"},"completions":{"type":"integer"},"completionRate":{"type":["number","null"],"minimum":0,"description":"Percentage, or null when the declared denominator is zero."},"contentStarts":{"type":"integer"},"contentResumes":{"type":"integer"},"activationRate":{"type":["number","null"],"minimum":0,"description":"Percentage, or null when the declared denominator is zero."},"quizStarts":{"type":"integer"},"quizAttempts":{"type":"integer"},"quizSubmissionRate":{"type":["number","null"],"minimum":0,"description":"Percentage, or null when the declared denominator is zero."},"averageQuizScore":{"type":["number","null"],"minimum":0,"description":"Percentage, or null when the declared denominator is zero."},"videoStarts":{"type":"integer"},"videoCompletions":{"type":"integer"},"videoCompletionRate":{"type":["number","null"],"minimum":0,"description":"Percentage, or null when the declared denominator is zero."},"certificatesEarned":{"type":"integer"},"certificateDownloads":{"type":"integer"},"certificateEarnedRate":{"type":["number","null"],"minimum":0,"description":"Percentage, or null when the declared denominator is zero."},"reviewParticipants":{"type":"integer"},"reviewParticipationRate":{"type":["number","null"],"minimum":0,"description":"Percentage, or null when the declared denominator is zero."},"sectionCompletions":{"type":"integer"},"referenceCompletions":{"type":"integer"},"medianTimeToStartSeconds":{"type":["number","null"]},"medianTimeToCompleteSeconds":{"type":["number","null"]},"inactiveLearners":{"type":"integer"},"returnedAfterInactivity":{"type":"integer"},"returnAfterInactivityRate":{"type":["number","null"],"minimum":0,"description":"Percentage, or null when the declared denominator is zero."}},"required":["enrollments","completions","completionRate","contentStarts","contentResumes","activationRate","quizStarts","quizAttempts","quizSubmissionRate","averageQuizScore","videoStarts","videoCompletions","videoCompletionRate","certificatesEarned","certificateDownloads","certificateEarnedRate","reviewParticipants","reviewParticipationRate","sectionCompletions","referenceCompletions","medianTimeToStartSeconds","medianTimeToCompleteSeconds","inactiveLearners","returnedAfterInactivity","returnAfterInactivityRate"]},"definitions":{"type":"object","properties":{"activationWindowDays":{"type":"number","const":7},"inactivityWindowDays":{"type":"number","const":14},"gamificationAvailable":{"type":"boolean","description":"False until accepted server-side gamification state exists."}},"required":["activationWindowDays","inactivityWindowDays","gamificationAvailable"]},"daily":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","format":"date"},"enrollments":{"type":"integer"},"completions":{"type":"integer"},"quizAttempts":{"type":"integer"},"averageQuizScore":{"type":["number","null"],"minimum":0,"description":"Percentage, or null when the declared denominator is zero."}},"required":["date","enrollments","completions","quizAttempts","averageQuizScore"]}}},"required":["metadata","totals","definitions","daily"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/insights/series":{"get":{"tags":["Insights"],"operationId":"getInsightsSeries","summary":"Daily insights series","description":"One data point per UTC calendar day for the chosen metric — the same series the dashboard's Insights charts plot. `enrollments` pairs new enrollments with completions, `quiz` tracks attempt volume and mean score, `revenue` tracks purchases, refunds and the amount collected (minor units, single-currency orgs only — mixed-currency orgs get null amounts, never a cross-currency sum).","parameters":[{"name":"metric","in":"query","required":true,"description":"Which daily series to return.","schema":{"type":"string","enum":["enrollments","quiz","revenue"]}},{"name":"from","in":"query","description":"Window start (UTC day, `YYYY-MM-DD`). Defaults to 29 days before `to`.","schema":{"type":"string","format":"date"}},{"name":"to","in":"query","description":"Window end (UTC day, `YYYY-MM-DD`, inclusive). Defaults to today.","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Daily insights series.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"metric":{"type":"string","enum":["enrollments","quiz","revenue"]},"from":{"type":"string","format":"date","description":"The resolved window start (UTC day)."},"to":{"type":"string","format":"date","description":"The resolved window end (UTC day, inclusive)."},"currency":{"description":"`revenue` only: the ISO currency code every `revenue` amount is in. Null for the other metrics, and for orgs selling in more than one currency.","type":["string","null"]},"points":{"type":"array","items":{"anyOf":[{"type":"object","properties":{"date":{"type":"string","format":"date","description":"The UTC calendar day."},"enrollments":{"type":"integer","description":"Enrollments created that day."},"completions":{"type":"integer","description":"Courses completed that day. Only enrollments created inside the window are counted."}},"required":["date","enrollments","completions"]},{"type":"object","properties":{"date":{"type":"string","format":"date","description":"The UTC calendar day."},"attempts":{"type":"integer","description":"Quiz attempts submitted that day."},"avgScorePct":{"type":["integer","null"],"description":"Mean score of the day's attempts as a percentage, 0–100. Null with no attempts."}},"required":["date","attempts","avgScorePct"]},{"type":"object","properties":{"date":{"type":"string","format":"date","description":"The UTC calendar day."},"purchases":{"type":"integer","description":"Paid, non-refunded purchases made that day."},"refunds":{"type":"integer","description":"Purchases made that day that were later refunded."},"revenue":{"type":["integer","null"],"description":"Revenue excluding refunded purchases that day, in the minor unit (cents) of the response's `currency`. Null when the org sells in more than one currency — amounts in different ISO codes cannot be summed; use `/sales` for per-currency totals."}},"required":["date","purchases","refunds","revenue"]}]},"description":"One point per day, oldest first. The shape follows the chosen metric."}},"required":["metric","from","to","currency","points"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/contents/{id}/insights":{"get":{"tags":["Insights"],"operationId":"getContentInsights","summary":"A content's insights","description":"The editor's course-scoped Insights. `academic` reuses the organization metric definitions and bounded UTC window, including referenced-material activity attributed to the enrolled course. Quiz questions, polls, and review summaries remain detailed complements.","parameters":[{"name":"id","in":"path","required":true,"description":"The content id.","schema":{"type":"string"}},{"name":"from","in":"query","description":"Inclusive UTC start. Defaults to 29 days before `to`. Maximum 366 days.","schema":{"type":"string","format":"date"}},{"name":"to","in":"query","description":"Inclusive UTC end. Defaults to today.","schema":{"type":"string","format":"date"}},{"name":"offerId","in":"query","description":"Limit results to one offer.","schema":{"type":"string"}},{"name":"cohortId","in":"query","description":"Limit academic results to one cohort.","schema":{"type":"string"}}],"responses":{"200":{"description":"A content's insights.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"academic":{"type":"object","properties":{"metadata":{"type":"object","properties":{"source":{"type":"string","const":"cursare","description":"Authoritative Cursare operational and event facts."},"metricVersion":{"type":"number","const":1,"description":"Version of the published metric definitions."},"from":{"type":"string","format":"date","description":"Resolved inclusive UTC window start."},"to":{"type":"string","format":"date","description":"Resolved inclusive UTC window end."},"generatedAt":{"type":"string","format":"date-time","description":"When this response was generated."},"freshThrough":{"type":"string","format":"date-time","description":"Latest boundary represented by the source."},"health":{"type":"string","enum":["current","partial"],"description":"Partial means consented interaction coverage is not yet available."}},"required":["source","metricVersion","from","to","generatedAt","freshThrough","health"]},"totals":{"type":"object","properties":{"enrollments":{"type":"integer"},"completions":{"type":"integer"},"completionRate":{"type":["number","null"],"minimum":0,"description":"Percentage, or null when the declared denominator is zero."},"contentStarts":{"type":"integer"},"contentResumes":{"type":"integer"},"activationRate":{"type":["number","null"],"minimum":0,"description":"Percentage, or null when the declared denominator is zero."},"quizStarts":{"type":"integer"},"quizAttempts":{"type":"integer"},"quizSubmissionRate":{"type":["number","null"],"minimum":0,"description":"Percentage, or null when the declared denominator is zero."},"averageQuizScore":{"type":["number","null"],"minimum":0,"description":"Percentage, or null when the declared denominator is zero."},"videoStarts":{"type":"integer"},"videoCompletions":{"type":"integer"},"videoCompletionRate":{"type":["number","null"],"minimum":0,"description":"Percentage, or null when the declared denominator is zero."},"certificatesEarned":{"type":"integer"},"certificateDownloads":{"type":"integer"},"certificateEarnedRate":{"type":["number","null"],"minimum":0,"description":"Percentage, or null when the declared denominator is zero."},"reviewParticipants":{"type":"integer"},"reviewParticipationRate":{"type":["number","null"],"minimum":0,"description":"Percentage, or null when the declared denominator is zero."},"sectionCompletions":{"type":"integer"},"referenceCompletions":{"type":"integer"},"medianTimeToStartSeconds":{"type":["number","null"]},"medianTimeToCompleteSeconds":{"type":["number","null"]},"inactiveLearners":{"type":"integer"},"returnedAfterInactivity":{"type":"integer"},"returnAfterInactivityRate":{"type":["number","null"],"minimum":0,"description":"Percentage, or null when the declared denominator is zero."}},"required":["enrollments","completions","completionRate","contentStarts","contentResumes","activationRate","quizStarts","quizAttempts","quizSubmissionRate","averageQuizScore","videoStarts","videoCompletions","videoCompletionRate","certificatesEarned","certificateDownloads","certificateEarnedRate","reviewParticipants","reviewParticipationRate","sectionCompletions","referenceCompletions","medianTimeToStartSeconds","medianTimeToCompleteSeconds","inactiveLearners","returnedAfterInactivity","returnAfterInactivityRate"]},"definitions":{"type":"object","properties":{"activationWindowDays":{"type":"number","const":7},"inactivityWindowDays":{"type":"number","const":14},"gamificationAvailable":{"type":"boolean","description":"False until accepted server-side gamification state exists."}},"required":["activationWindowDays","inactivityWindowDays","gamificationAvailable"]},"daily":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","format":"date"},"enrollments":{"type":"integer"},"completions":{"type":"integer"},"quizAttempts":{"type":"integer"},"averageQuizScore":{"type":["number","null"],"minimum":0,"description":"Percentage, or null when the declared denominator is zero."}},"required":["date","enrollments","completions","quizAttempts","averageQuizScore"]}}},"required":["metadata","totals","definitions","daily"]},"learners":{"type":"object","properties":{"enrolled":{"type":"integer","description":"Enrollments created in the resolved UTC window."},"completed":{"type":"integer","description":"Course completions recorded in the resolved UTC window."},"completionRate":{"type":["number","null"],"minimum":0,"description":"Completed eligible learners divided by the stable eligible population."}},"required":["enrolled","completed","completionRate"]},"quiz":{"type":"object","properties":{"attempts":{"type":"integer","description":"Graded quiz attempts in the resolved UTC window."},"avgScorePct":{"description":"Mean score across attempts in the resolved window, 0–100. Null with none.","type":["number","null"]},"questions":{"type":"array","items":{"type":"object","properties":{"questionId":{"type":"string"},"prompt":{"type":"string"},"attempts":{"type":"integer","description":"How many attempts answered this question."},"correctPct":{"type":"integer","description":"Share of attempts answered correctly, 0–100."}},"required":["questionId","prompt","attempts","correctPct"]},"description":"Per-question accuracy, hardest first. Graded against the current answer key."}},"required":["attempts","avgScorePct","questions"]},"polls":{"type":"array","items":{"type":"object","properties":{"pollId":{"type":"string"},"question":{"type":"string"},"total":{"type":"integer","description":"Total votes cast."},"options":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"text":{"type":"string"},"votes":{"type":"integer"}},"required":["id","text","votes"]}}},"required":["pollId","question","total","options"]}},"reviews":{"type":"object","properties":{"average":{"type":"number","description":"Mean rating, 1–5. 0 when there are no reviews."},"count":{"type":"integer"}},"required":["average","count"]}},"required":["academic","learners","quiz","polls","reviews"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/contents/{id}/sales":{"get":{"tags":["Insights"],"operationId":"getContentSales","summary":"A content's sales","description":"Sales summary for one content, net of refunds: purchase count, revenue in the content's currency (minor units), and the most recent buyers.","parameters":[{"name":"id","in":"path","required":true,"description":"The content id.","schema":{"type":"string"}}],"responses":{"200":{"description":"A content's sales.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"count":{"type":"integer","description":"Purchases, net of refunds."},"revenue":{"type":"integer","description":"Total collected, in the currency's minor unit (cents)."},"currency":{"type":"string","description":"ISO currency code the revenue is in, e.g. `BRL`."},"recent":{"type":"array","items":{"type":"object","properties":{"buyerName":{"type":"string"},"amount":{"type":"integer","description":"Amount paid, in the currency's minor unit (cents)."},"createdAt":{"type":"string","format":"date-time"}},"required":["buyerName","amount","createdAt"]},"description":"The 10 most recent non-refunded purchases, newest first."}},"required":["count","revenue","currency","recent"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/integrations":{"get":{"tags":["Integrations"],"operationId":"getIntegrations","summary":"Get the four organization integration capabilities","description":"Returns secret-free status for Payments, Video, WhatsApp, and Google analytics. This is the only aggregate integration status operation. MCP, native affiliates, transactional email, API keys, and webhooks are separate platform capabilities.","responses":{"200":{"description":"Get the four organization integration capabilities.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"payments":{"type":"object","properties":{"id":{"description":"Stable id used by signed external-payment callbacks.","type":["string","null"]},"connected":{"type":"boolean"},"state":{"type":"string","enum":["not_connected","setup_required","connected","attention"],"description":"The derived connection state. Credentials are never included."},"provider":{"type":["string","null"],"enum":["stripe","external"]},"accountId":{"description":"Safe provider account identity.","type":["string","null"]},"name":{"description":"External checkout display name.","type":["string","null"]},"checkoutUrl":{"type":["string","null"],"format":"uri","description":"External checkout destination."}},"required":["id","connected","state","provider","accountId","name","checkoutUrl"]},"video":{"type":"object","properties":{"connected":{"type":"boolean"},"state":{"type":"string","enum":["not_connected","setup_required","connected","attention"],"description":"The derived connection state. Credentials are never included."},"provider":{"type":["string","null"],"enum":["cloudflare","mux"]},"accountId":{"description":"Safe provider credential id. The secret is never returned.","type":["string","null"]}},"required":["connected","state","provider","accountId"]},"whatsapp":{"type":"object","properties":{"connected":{"type":"boolean"},"state":{"type":"string","enum":["not_connected","setup_required","connected","attention"],"description":"The derived connection state. Credentials are never included."},"phoneNumber":{"description":"Connected WhatsApp display number.","type":["string","null"]},"notifyNumbers":{"type":"array","items":{"type":"string"},"description":"Operational-notification recipients. An empty list disables staff notifications and allows a study-only connection."},"templateName":{"description":"Approved message template, when configured.","type":["string","null"]},"templateLanguage":{"description":"Configured template locale.","type":["string","null"]}},"required":["connected","state","phoneNumber","notifyNumbers","templateName","templateLanguage"]},"analytics":{"type":"object","properties":{"state":{"type":"string","enum":["not_connected","setup_required","connected","attention"],"description":"The derived connection state. Credentials are never included."},"connected":{"type":"boolean"},"identityEmail":{"description":"Safe email of the connected Google identity.","type":["string","null"]},"method":{"type":["string","null"],"enum":["direct_ga4","gtm"]},"active":{"type":"boolean"},"resource":{"type":["object","null"],"properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"]},"issueCode":{"type":["string","null"],"enum":["authorization_revoked","insufficient_scope","resource_unavailable","provider_unavailable"]},"grantedCapabilities":{"type":"object","properties":{"analyticsRead":{"type":"boolean"},"tagManagerRead":{"type":"boolean"},"tagManagerManage":{"type":"boolean"}},"required":["analyticsRead","tagManagerRead","tagManagerManage"]},"managedGtm":{"type":["object","null"],"properties":{"catalogVersion":{"type":"number","const":1,"description":"Canonical Cursare analytics catalog version."},"destination":{"type":"object","properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"],"description":"GA4 web stream that receives managed events."},"preview":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["tag","trigger","variable"]},"name":{"type":"string"},"action":{"type":"string","enum":["create","update"]}},"required":["kind","name","action"]}},"fingerprint":{"type":"string","minLength":64,"maxLength":64,"description":"Fingerprint of the exact pending preview."},"publishedAt":{"type":["string","null"],"format":"date-time"}},"required":["catalogVersion","destination","preview","fingerprint","publishedAt"]},"serverDelivery":{"type":"object","properties":{"configured":{"type":"boolean","description":"Whether encrypted GA4 Measurement Protocol credentials are configured."},"measurementId":{"description":"Safe GA4 measurement id. The API secret is never returned.","type":["string","null"]},"issueCode":{"type":["string","null"],"enum":["credentials_rejected","provider_unavailable"],"description":"Last actionable server-delivery health issue, if any."}},"required":["configured","measurementId","issueCode"]},"reporting":{"type":"object","properties":{"connected":{"type":"boolean","description":"Whether Analytics read access and a property are available."},"resource":{"type":["object","null"],"properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"],"description":"The GA4 web stream used for reports."},"issueCode":{"type":["string","null"],"enum":["authorization_revoked","insufficient_scope","resource_unavailable","provider_unavailable"],"description":"An Analytics reporting issue independent from browser and server delivery."},"revision":{"type":"string","description":"Changes whenever a reporting selection is replaced."}},"required":["connected","resource","issueCode","revision"]}},"required":["state","connected","identityEmail","method","active","resource","issueCode","grantedCapabilities","managedGtm","serverDelivery","reporting"]}},"required":["payments","video","whatsapp","analytics"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/integrations/google":{"get":{"tags":["Integrations"],"operationId":"getGoogleIntegration","summary":"Get Google integration status","description":"Returns the safe Google identity, chosen delivery method, named resource, activation state, granted capabilities, and actionable issue code. Tokens are never returned.","responses":{"200":{"description":"Get Google integration status.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"state":{"type":"string","enum":["not_connected","setup_required","connected","attention"],"description":"The derived connection state. Credentials are never included."},"connected":{"type":"boolean"},"identityEmail":{"description":"Safe email of the connected Google identity.","type":["string","null"]},"method":{"type":["string","null"],"enum":["direct_ga4","gtm"]},"active":{"type":"boolean"},"resource":{"type":["object","null"],"properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"]},"issueCode":{"type":["string","null"],"enum":["authorization_revoked","insufficient_scope","resource_unavailable","provider_unavailable"]},"grantedCapabilities":{"type":"object","properties":{"analyticsRead":{"type":"boolean"},"tagManagerRead":{"type":"boolean"},"tagManagerManage":{"type":"boolean"}},"required":["analyticsRead","tagManagerRead","tagManagerManage"]},"managedGtm":{"type":["object","null"],"properties":{"catalogVersion":{"type":"number","const":1,"description":"Canonical Cursare analytics catalog version."},"destination":{"type":"object","properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"],"description":"GA4 web stream that receives managed events."},"preview":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["tag","trigger","variable"]},"name":{"type":"string"},"action":{"type":"string","enum":["create","update"]}},"required":["kind","name","action"]}},"fingerprint":{"type":"string","minLength":64,"maxLength":64,"description":"Fingerprint of the exact pending preview."},"publishedAt":{"type":["string","null"],"format":"date-time"}},"required":["catalogVersion","destination","preview","fingerprint","publishedAt"]},"serverDelivery":{"type":"object","properties":{"configured":{"type":"boolean","description":"Whether encrypted GA4 Measurement Protocol credentials are configured."},"measurementId":{"description":"Safe GA4 measurement id. The API secret is never returned.","type":["string","null"]},"issueCode":{"type":["string","null"],"enum":["credentials_rejected","provider_unavailable"],"description":"Last actionable server-delivery health issue, if any."}},"required":["configured","measurementId","issueCode"]},"reporting":{"type":"object","properties":{"connected":{"type":"boolean","description":"Whether Analytics read access and a property are available."},"resource":{"type":["object","null"],"properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"],"description":"The GA4 web stream used for reports."},"issueCode":{"type":["string","null"],"enum":["authorization_revoked","insufficient_scope","resource_unavailable","provider_unavailable"],"description":"An Analytics reporting issue independent from browser and server delivery."},"revision":{"type":"string","description":"Changes whenever a reporting selection is replaced."}},"required":["connected","resource","issueCode","revision"]}},"required":["state","connected","identityEmail","method","active","resource","issueCode","grantedCapabilities","managedGtm","serverDelivery","reporting"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"tags":["Integrations"],"operationId":"disconnectGoogleIntegration","summary":"Disconnect Google","description":"Deletes the encrypted refresh token, identity, selections, managed drafts, and public tracking projection. It does not change Google resources. Organization administrator only.","responses":{"200":{"description":"Disconnect Google.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"deleted":{"type":"boolean","const":true}},"required":["deleted"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/integrations/google/authorize":{"post":{"tags":["Integrations"],"operationId":"authorizeGoogleIntegration","summary":"Start Google authorization","description":"Starts session-bound Google OAuth with PKCE for either read-only Google Analytics discovery or read-only Tag Manager discovery. Must be opened from the active organization browser session. Organization administrator only.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"method":{"type":"string","enum":["direct_ga4","gtm"],"description":"The exclusive delivery method being configured."}},"required":["method"]}}}},"responses":{"200":{"description":"Start Google authorization.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"authorizationUrl":{"type":"string","format":"uri","description":"Google authorization URL to open in this browser."}},"required":["authorizationUrl"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/integrations/google/reconnect":{"post":{"tags":["Integrations"],"operationId":"reconnectGoogleIntegration","summary":"Reconnect or replace the Google identity","description":"Starts a new PKCE authorization for the selected method. A different Google identity clears prior resource selections before it can be activated. Organization administrator only.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"method":{"type":"string","enum":["direct_ga4","gtm"]}},"required":["method"]}}}},"responses":{"200":{"description":"Reconnect or replace the Google identity.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"authorizationUrl":{"type":"string","format":"uri"}},"required":["authorizationUrl"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/integrations/google/resources":{"get":{"tags":["Integrations"],"operationId":"listGoogleResources","summary":"List accessible Google resources","description":"Discovers human-readable GA4 web streams or GTM web containers available to the connected identity. Raw identifiers cannot be submitted without appearing in this result. Organization administrator only.","parameters":[{"name":"method","in":"query","required":true,"schema":{"type":"string","enum":["direct_ga4","gtm"]}}],"responses":{"200":{"description":"List accessible Google resources.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"]}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/integrations/google/resource":{"put":{"tags":["Integrations"],"operationId":"selectGoogleResource","summary":"Select a discovered Google resource","description":"Re-discovers provider resources and accepts only a resource the connected identity can currently access. Selection does not activate tracking. Organization administrator only.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"method":{"type":"string","enum":["direct_ga4","gtm"]},"resourceId":{"type":"string","minLength":1,"description":"Provider resource path returned by discovery."}},"required":["method","resourceId"]}}}},"responses":{"200":{"description":"Select a discovered Google resource.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"state":{"type":"string","enum":["not_connected","setup_required","connected","attention"],"description":"The derived connection state. Credentials are never included."},"connected":{"type":"boolean"},"identityEmail":{"description":"Safe email of the connected Google identity.","type":["string","null"]},"method":{"type":["string","null"],"enum":["direct_ga4","gtm"]},"active":{"type":"boolean"},"resource":{"type":["object","null"],"properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"]},"issueCode":{"type":["string","null"],"enum":["authorization_revoked","insufficient_scope","resource_unavailable","provider_unavailable"]},"grantedCapabilities":{"type":"object","properties":{"analyticsRead":{"type":"boolean"},"tagManagerRead":{"type":"boolean"},"tagManagerManage":{"type":"boolean"}},"required":["analyticsRead","tagManagerRead","tagManagerManage"]},"managedGtm":{"type":["object","null"],"properties":{"catalogVersion":{"type":"number","const":1,"description":"Canonical Cursare analytics catalog version."},"destination":{"type":"object","properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"],"description":"GA4 web stream that receives managed events."},"preview":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["tag","trigger","variable"]},"name":{"type":"string"},"action":{"type":"string","enum":["create","update"]}},"required":["kind","name","action"]}},"fingerprint":{"type":"string","minLength":64,"maxLength":64,"description":"Fingerprint of the exact pending preview."},"publishedAt":{"type":["string","null"],"format":"date-time"}},"required":["catalogVersion","destination","preview","fingerprint","publishedAt"]},"serverDelivery":{"type":"object","properties":{"configured":{"type":"boolean","description":"Whether encrypted GA4 Measurement Protocol credentials are configured."},"measurementId":{"description":"Safe GA4 measurement id. The API secret is never returned.","type":["string","null"]},"issueCode":{"type":["string","null"],"enum":["credentials_rejected","provider_unavailable"],"description":"Last actionable server-delivery health issue, if any."}},"required":["configured","measurementId","issueCode"]},"reporting":{"type":"object","properties":{"connected":{"type":"boolean","description":"Whether Analytics read access and a property are available."},"resource":{"type":["object","null"],"properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"],"description":"The GA4 web stream used for reports."},"issueCode":{"type":["string","null"],"enum":["authorization_revoked","insufficient_scope","resource_unavailable","provider_unavailable"],"description":"An Analytics reporting issue independent from browser and server delivery."},"revision":{"type":"string","description":"Changes whenever a reporting selection is replaced."}},"required":["connected","resource","issueCode","revision"]}},"required":["state","connected","identityEmail","method","active","resource","issueCode","grantedCapabilities","managedGtm","serverDelivery","reporting"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/integrations/google/activate":{"post":{"tags":["Integrations"],"operationId":"activateGoogleIntegration","summary":"Activate the selected Google delivery method","description":"Activates exactly one selected GA4 or GTM resource for eligible public tenant pages. Consent still controls whether the script loads. Organization administrator only.","responses":{"200":{"description":"Activate the selected Google delivery method.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"state":{"type":"string","enum":["not_connected","setup_required","connected","attention"],"description":"The derived connection state. Credentials are never included."},"connected":{"type":"boolean"},"identityEmail":{"description":"Safe email of the connected Google identity.","type":["string","null"]},"method":{"type":["string","null"],"enum":["direct_ga4","gtm"]},"active":{"type":"boolean"},"resource":{"type":["object","null"],"properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"]},"issueCode":{"type":["string","null"],"enum":["authorization_revoked","insufficient_scope","resource_unavailable","provider_unavailable"]},"grantedCapabilities":{"type":"object","properties":{"analyticsRead":{"type":"boolean"},"tagManagerRead":{"type":"boolean"},"tagManagerManage":{"type":"boolean"}},"required":["analyticsRead","tagManagerRead","tagManagerManage"]},"managedGtm":{"type":["object","null"],"properties":{"catalogVersion":{"type":"number","const":1,"description":"Canonical Cursare analytics catalog version."},"destination":{"type":"object","properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"],"description":"GA4 web stream that receives managed events."},"preview":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["tag","trigger","variable"]},"name":{"type":"string"},"action":{"type":"string","enum":["create","update"]}},"required":["kind","name","action"]}},"fingerprint":{"type":"string","minLength":64,"maxLength":64,"description":"Fingerprint of the exact pending preview."},"publishedAt":{"type":["string","null"],"format":"date-time"}},"required":["catalogVersion","destination","preview","fingerprint","publishedAt"]},"serverDelivery":{"type":"object","properties":{"configured":{"type":"boolean","description":"Whether encrypted GA4 Measurement Protocol credentials are configured."},"measurementId":{"description":"Safe GA4 measurement id. The API secret is never returned.","type":["string","null"]},"issueCode":{"type":["string","null"],"enum":["credentials_rejected","provider_unavailable"],"description":"Last actionable server-delivery health issue, if any."}},"required":["configured","measurementId","issueCode"]},"reporting":{"type":"object","properties":{"connected":{"type":"boolean","description":"Whether Analytics read access and a property are available."},"resource":{"type":["object","null"],"properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"],"description":"The GA4 web stream used for reports."},"issueCode":{"type":["string","null"],"enum":["authorization_revoked","insufficient_scope","resource_unavailable","provider_unavailable"],"description":"An Analytics reporting issue independent from browser and server delivery."},"revision":{"type":"string","description":"Changes whenever a reporting selection is replaced."}},"required":["connected","resource","issueCode","revision"]}},"required":["state","connected","identityEmail","method","active","resource","issueCode","grantedCapabilities","managedGtm","serverDelivery","reporting"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/integrations/google/disable":{"post":{"tags":["Integrations"],"operationId":"disableGoogleIntegration","summary":"Disable Google tracking","description":"Stops public script delivery while preserving the identity, method, and resource so setup can be resumed. Organization administrator only.","responses":{"200":{"description":"Disable Google tracking.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"state":{"type":"string","enum":["not_connected","setup_required","connected","attention"],"description":"The derived connection state. Credentials are never included."},"connected":{"type":"boolean"},"identityEmail":{"description":"Safe email of the connected Google identity.","type":["string","null"]},"method":{"type":["string","null"],"enum":["direct_ga4","gtm"]},"active":{"type":"boolean"},"resource":{"type":["object","null"],"properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"]},"issueCode":{"type":["string","null"],"enum":["authorization_revoked","insufficient_scope","resource_unavailable","provider_unavailable"]},"grantedCapabilities":{"type":"object","properties":{"analyticsRead":{"type":"boolean"},"tagManagerRead":{"type":"boolean"},"tagManagerManage":{"type":"boolean"}},"required":["analyticsRead","tagManagerRead","tagManagerManage"]},"managedGtm":{"type":["object","null"],"properties":{"catalogVersion":{"type":"number","const":1,"description":"Canonical Cursare analytics catalog version."},"destination":{"type":"object","properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"],"description":"GA4 web stream that receives managed events."},"preview":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["tag","trigger","variable"]},"name":{"type":"string"},"action":{"type":"string","enum":["create","update"]}},"required":["kind","name","action"]}},"fingerprint":{"type":"string","minLength":64,"maxLength":64,"description":"Fingerprint of the exact pending preview."},"publishedAt":{"type":["string","null"],"format":"date-time"}},"required":["catalogVersion","destination","preview","fingerprint","publishedAt"]},"serverDelivery":{"type":"object","properties":{"configured":{"type":"boolean","description":"Whether encrypted GA4 Measurement Protocol credentials are configured."},"measurementId":{"description":"Safe GA4 measurement id. The API secret is never returned.","type":["string","null"]},"issueCode":{"type":["string","null"],"enum":["credentials_rejected","provider_unavailable"],"description":"Last actionable server-delivery health issue, if any."}},"required":["configured","measurementId","issueCode"]},"reporting":{"type":"object","properties":{"connected":{"type":"boolean","description":"Whether Analytics read access and a property are available."},"resource":{"type":["object","null"],"properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"],"description":"The GA4 web stream used for reports."},"issueCode":{"type":["string","null"],"enum":["authorization_revoked","insufficient_scope","resource_unavailable","provider_unavailable"],"description":"An Analytics reporting issue independent from browser and server delivery."},"revision":{"type":"string","description":"Changes whenever a reporting selection is replaced."}},"required":["connected","resource","issueCode","revision"]}},"required":["state","connected","identityEmail","method","active","resource","issueCode","grantedCapabilities","managedGtm","serverDelivery","reporting"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/integrations/google/server-delivery":{"put":{"tags":["Integrations"],"operationId":"configureGoogleServerDelivery","summary":"Configure reliable GA4 server delivery","description":"Encrypts an organization-owned GA4 Measurement Protocol secret for consent-linked server events. The secret is write-only and is never returned by status or API responses. Organization administrator only.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"measurementId":{"type":"string"},"apiSecret":{"type":"string","minLength":8,"maxLength":256}},"required":["measurementId","apiSecret"]}}}},"responses":{"200":{"description":"Configure reliable GA4 server delivery.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"state":{"type":"string","enum":["not_connected","setup_required","connected","attention"],"description":"The derived connection state. Credentials are never included."},"connected":{"type":"boolean"},"identityEmail":{"description":"Safe email of the connected Google identity.","type":["string","null"]},"method":{"type":["string","null"],"enum":["direct_ga4","gtm"]},"active":{"type":"boolean"},"resource":{"type":["object","null"],"properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"]},"issueCode":{"type":["string","null"],"enum":["authorization_revoked","insufficient_scope","resource_unavailable","provider_unavailable"]},"grantedCapabilities":{"type":"object","properties":{"analyticsRead":{"type":"boolean"},"tagManagerRead":{"type":"boolean"},"tagManagerManage":{"type":"boolean"}},"required":["analyticsRead","tagManagerRead","tagManagerManage"]},"managedGtm":{"type":["object","null"],"properties":{"catalogVersion":{"type":"number","const":1,"description":"Canonical Cursare analytics catalog version."},"destination":{"type":"object","properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"],"description":"GA4 web stream that receives managed events."},"preview":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["tag","trigger","variable"]},"name":{"type":"string"},"action":{"type":"string","enum":["create","update"]}},"required":["kind","name","action"]}},"fingerprint":{"type":"string","minLength":64,"maxLength":64,"description":"Fingerprint of the exact pending preview."},"publishedAt":{"type":["string","null"],"format":"date-time"}},"required":["catalogVersion","destination","preview","fingerprint","publishedAt"]},"serverDelivery":{"type":"object","properties":{"configured":{"type":"boolean","description":"Whether encrypted GA4 Measurement Protocol credentials are configured."},"measurementId":{"description":"Safe GA4 measurement id. The API secret is never returned.","type":["string","null"]},"issueCode":{"type":["string","null"],"enum":["credentials_rejected","provider_unavailable"],"description":"Last actionable server-delivery health issue, if any."}},"required":["configured","measurementId","issueCode"]},"reporting":{"type":"object","properties":{"connected":{"type":"boolean","description":"Whether Analytics read access and a property are available."},"resource":{"type":["object","null"],"properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"],"description":"The GA4 web stream used for reports."},"issueCode":{"type":["string","null"],"enum":["authorization_revoked","insufficient_scope","resource_unavailable","provider_unavailable"],"description":"An Analytics reporting issue independent from browser and server delivery."},"revision":{"type":"string","description":"Changes whenever a reporting selection is replaced."}},"required":["connected","resource","issueCode","revision"]}},"required":["state","connected","identityEmail","method","active","resource","issueCode","grantedCapabilities","managedGtm","serverDelivery","reporting"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"tags":["Integrations"],"operationId":"clearGoogleServerDelivery","summary":"Disable reliable GA4 server delivery","description":"Deletes the encrypted Measurement Protocol secret and stops future server delivery without changing authoritative Cursare facts or browser tracking. Organization administrator only.","responses":{"200":{"description":"Disable reliable GA4 server delivery.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"state":{"type":"string","enum":["not_connected","setup_required","connected","attention"],"description":"The derived connection state. Credentials are never included."},"connected":{"type":"boolean"},"identityEmail":{"description":"Safe email of the connected Google identity.","type":["string","null"]},"method":{"type":["string","null"],"enum":["direct_ga4","gtm"]},"active":{"type":"boolean"},"resource":{"type":["object","null"],"properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"]},"issueCode":{"type":["string","null"],"enum":["authorization_revoked","insufficient_scope","resource_unavailable","provider_unavailable"]},"grantedCapabilities":{"type":"object","properties":{"analyticsRead":{"type":"boolean"},"tagManagerRead":{"type":"boolean"},"tagManagerManage":{"type":"boolean"}},"required":["analyticsRead","tagManagerRead","tagManagerManage"]},"managedGtm":{"type":["object","null"],"properties":{"catalogVersion":{"type":"number","const":1,"description":"Canonical Cursare analytics catalog version."},"destination":{"type":"object","properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"],"description":"GA4 web stream that receives managed events."},"preview":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["tag","trigger","variable"]},"name":{"type":"string"},"action":{"type":"string","enum":["create","update"]}},"required":["kind","name","action"]}},"fingerprint":{"type":"string","minLength":64,"maxLength":64,"description":"Fingerprint of the exact pending preview."},"publishedAt":{"type":["string","null"],"format":"date-time"}},"required":["catalogVersion","destination","preview","fingerprint","publishedAt"]},"serverDelivery":{"type":"object","properties":{"configured":{"type":"boolean","description":"Whether encrypted GA4 Measurement Protocol credentials are configured."},"measurementId":{"description":"Safe GA4 measurement id. The API secret is never returned.","type":["string","null"]},"issueCode":{"type":["string","null"],"enum":["credentials_rejected","provider_unavailable"],"description":"Last actionable server-delivery health issue, if any."}},"required":["configured","measurementId","issueCode"]},"reporting":{"type":"object","properties":{"connected":{"type":"boolean","description":"Whether Analytics read access and a property are available."},"resource":{"type":["object","null"],"properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"],"description":"The GA4 web stream used for reports."},"issueCode":{"type":["string","null"],"enum":["authorization_revoked","insufficient_scope","resource_unavailable","provider_unavailable"],"description":"An Analytics reporting issue independent from browser and server delivery."},"revision":{"type":"string","description":"Changes whenever a reporting selection is replaced."}},"required":["connected","resource","issueCode","revision"]}},"required":["state","connected","identityEmail","method","active","resource","issueCode","grantedCapabilities","managedGtm","serverDelivery","reporting"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/integrations/google/reporting":{"put":{"tags":["Integrations"],"operationId":"selectGoogleReportingResource","summary":"Select the GA4 property used by Insights","description":"Re-discovers accessible GA4 web streams and selects one for source-labeled acquisition reports. This capability is independent from browser and Measurement Protocol delivery. Organization administrator only.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"resourceId":{"type":"string","minLength":1,"description":"A GA4 web stream returned by resource discovery."}},"required":["resourceId"]}}}},"responses":{"200":{"description":"Select the GA4 property used by Insights.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"state":{"type":"string","enum":["not_connected","setup_required","connected","attention"],"description":"The derived connection state. Credentials are never included."},"connected":{"type":"boolean"},"identityEmail":{"description":"Safe email of the connected Google identity.","type":["string","null"]},"method":{"type":["string","null"],"enum":["direct_ga4","gtm"]},"active":{"type":"boolean"},"resource":{"type":["object","null"],"properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"]},"issueCode":{"type":["string","null"],"enum":["authorization_revoked","insufficient_scope","resource_unavailable","provider_unavailable"]},"grantedCapabilities":{"type":"object","properties":{"analyticsRead":{"type":"boolean"},"tagManagerRead":{"type":"boolean"},"tagManagerManage":{"type":"boolean"}},"required":["analyticsRead","tagManagerRead","tagManagerManage"]},"managedGtm":{"type":["object","null"],"properties":{"catalogVersion":{"type":"number","const":1,"description":"Canonical Cursare analytics catalog version."},"destination":{"type":"object","properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"],"description":"GA4 web stream that receives managed events."},"preview":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["tag","trigger","variable"]},"name":{"type":"string"},"action":{"type":"string","enum":["create","update"]}},"required":["kind","name","action"]}},"fingerprint":{"type":"string","minLength":64,"maxLength":64,"description":"Fingerprint of the exact pending preview."},"publishedAt":{"type":["string","null"],"format":"date-time"}},"required":["catalogVersion","destination","preview","fingerprint","publishedAt"]},"serverDelivery":{"type":"object","properties":{"configured":{"type":"boolean","description":"Whether encrypted GA4 Measurement Protocol credentials are configured."},"measurementId":{"description":"Safe GA4 measurement id. The API secret is never returned.","type":["string","null"]},"issueCode":{"type":["string","null"],"enum":["credentials_rejected","provider_unavailable"],"description":"Last actionable server-delivery health issue, if any."}},"required":["configured","measurementId","issueCode"]},"reporting":{"type":"object","properties":{"connected":{"type":"boolean","description":"Whether Analytics read access and a property are available."},"resource":{"type":["object","null"],"properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"],"description":"The GA4 web stream used for reports."},"issueCode":{"type":["string","null"],"enum":["authorization_revoked","insufficient_scope","resource_unavailable","provider_unavailable"],"description":"An Analytics reporting issue independent from browser and server delivery."},"revision":{"type":"string","description":"Changes whenever a reporting selection is replaced."}},"required":["connected","resource","issueCode","revision"]}},"required":["state","connected","identityEmail","method","active","resource","issueCode","grantedCapabilities","managedGtm","serverDelivery","reporting"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"tags":["Integrations"],"operationId":"clearGoogleReportingResource","summary":"Disconnect Google reports from Insights","description":"Clears the separately selected GA4 reporting property. Cursare's internal insights and Google delivery settings remain unchanged. Organization administrator only.","responses":{"200":{"description":"Disconnect Google reports from Insights.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"state":{"type":"string","enum":["not_connected","setup_required","connected","attention"],"description":"The derived connection state. Credentials are never included."},"connected":{"type":"boolean"},"identityEmail":{"description":"Safe email of the connected Google identity.","type":["string","null"]},"method":{"type":["string","null"],"enum":["direct_ga4","gtm"]},"active":{"type":"boolean"},"resource":{"type":["object","null"],"properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"]},"issueCode":{"type":["string","null"],"enum":["authorization_revoked","insufficient_scope","resource_unavailable","provider_unavailable"]},"grantedCapabilities":{"type":"object","properties":{"analyticsRead":{"type":"boolean"},"tagManagerRead":{"type":"boolean"},"tagManagerManage":{"type":"boolean"}},"required":["analyticsRead","tagManagerRead","tagManagerManage"]},"managedGtm":{"type":["object","null"],"properties":{"catalogVersion":{"type":"number","const":1,"description":"Canonical Cursare analytics catalog version."},"destination":{"type":"object","properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"],"description":"GA4 web stream that receives managed events."},"preview":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["tag","trigger","variable"]},"name":{"type":"string"},"action":{"type":"string","enum":["create","update"]}},"required":["kind","name","action"]}},"fingerprint":{"type":"string","minLength":64,"maxLength":64,"description":"Fingerprint of the exact pending preview."},"publishedAt":{"type":["string","null"],"format":"date-time"}},"required":["catalogVersion","destination","preview","fingerprint","publishedAt"]},"serverDelivery":{"type":"object","properties":{"configured":{"type":"boolean","description":"Whether encrypted GA4 Measurement Protocol credentials are configured."},"measurementId":{"description":"Safe GA4 measurement id. The API secret is never returned.","type":["string","null"]},"issueCode":{"type":["string","null"],"enum":["credentials_rejected","provider_unavailable"],"description":"Last actionable server-delivery health issue, if any."}},"required":["configured","measurementId","issueCode"]},"reporting":{"type":"object","properties":{"connected":{"type":"boolean","description":"Whether Analytics read access and a property are available."},"resource":{"type":["object","null"],"properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"],"description":"The GA4 web stream used for reports."},"issueCode":{"type":["string","null"],"enum":["authorization_revoked","insufficient_scope","resource_unavailable","provider_unavailable"],"description":"An Analytics reporting issue independent from browser and server delivery."},"revision":{"type":"string","description":"Changes whenever a reporting selection is replaced."}},"required":["connected","resource","issueCode","revision"]}},"required":["state","connected","identityEmail","method","active","resource","issueCode","grantedCapabilities","managedGtm","serverDelivery","reporting"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/integrations/google/reporting/authorize":{"post":{"tags":["Integrations"],"operationId":"authorizeGoogleReporting","summary":"Authorize Google Analytics report access","description":"Starts incremental, session-bound OAuth consent for read-only Analytics reports without enabling Tag Manager management or changing the selected browser delivery method. Organization administrator only.","responses":{"200":{"description":"Authorize Google Analytics report access.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"authorizationUrl":{"type":"string","format":"uri"}},"required":["authorizationUrl"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/integrations/google/oauth-result":{"get":{"tags":["Integrations"],"operationId":"getGoogleOauthResult","summary":"Resume Google setup after OAuth","description":"Returns the current safe status together with the browser callback outcome so an interrupted or completed wizard can resume from persisted setup state.","parameters":[{"name":"result","in":"query","required":true,"description":"OAuth callback outcome.","schema":{"type":"string","enum":["connected","cancelled","failed"]}}],"responses":{"200":{"description":"Resume Google setup after OAuth.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"result":{"type":"string","enum":["connected","cancelled","failed"]},"status":{"type":"object","properties":{"state":{"type":"string","enum":["not_connected","setup_required","connected","attention"],"description":"The derived connection state. Credentials are never included."},"connected":{"type":"boolean"},"identityEmail":{"description":"Safe email of the connected Google identity.","type":["string","null"]},"method":{"type":["string","null"],"enum":["direct_ga4","gtm"]},"active":{"type":"boolean"},"resource":{"type":["object","null"],"properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"]},"issueCode":{"type":["string","null"],"enum":["authorization_revoked","insufficient_scope","resource_unavailable","provider_unavailable"]},"grantedCapabilities":{"type":"object","properties":{"analyticsRead":{"type":"boolean"},"tagManagerRead":{"type":"boolean"},"tagManagerManage":{"type":"boolean"}},"required":["analyticsRead","tagManagerRead","tagManagerManage"]},"managedGtm":{"type":["object","null"],"properties":{"catalogVersion":{"type":"number","const":1,"description":"Canonical Cursare analytics catalog version."},"destination":{"type":"object","properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"],"description":"GA4 web stream that receives managed events."},"preview":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["tag","trigger","variable"]},"name":{"type":"string"},"action":{"type":"string","enum":["create","update"]}},"required":["kind","name","action"]}},"fingerprint":{"type":"string","minLength":64,"maxLength":64,"description":"Fingerprint of the exact pending preview."},"publishedAt":{"type":["string","null"],"format":"date-time"}},"required":["catalogVersion","destination","preview","fingerprint","publishedAt"]},"serverDelivery":{"type":"object","properties":{"configured":{"type":"boolean","description":"Whether encrypted GA4 Measurement Protocol credentials are configured."},"measurementId":{"description":"Safe GA4 measurement id. The API secret is never returned.","type":["string","null"]},"issueCode":{"type":["string","null"],"enum":["credentials_rejected","provider_unavailable"],"description":"Last actionable server-delivery health issue, if any."}},"required":["configured","measurementId","issueCode"]},"reporting":{"type":"object","properties":{"connected":{"type":"boolean","description":"Whether Analytics read access and a property are available."},"resource":{"type":["object","null"],"properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"],"description":"The GA4 web stream used for reports."},"issueCode":{"type":["string","null"],"enum":["authorization_revoked","insufficient_scope","resource_unavailable","provider_unavailable"],"description":"An Analytics reporting issue independent from browser and server delivery."},"revision":{"type":"string","description":"Changes whenever a reporting selection is replaced."}},"required":["connected","resource","issueCode","revision"]}},"required":["state","connected","identityEmail","method","active","resource","issueCode","grantedCapabilities","managedGtm","serverDelivery","reporting"]}},"required":["result","status"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/integrations/google/gtm/authorize":{"post":{"tags":["Integrations"],"operationId":"authorizeGoogleGtmManagement","summary":"Authorize managed Tag Manager setup","description":"Starts incremental Google consent for Analytics discovery plus Tag Manager edit and publish access. The existing read-only connection remains usable if consent is cancelled. Organization administrator only.","responses":{"200":{"description":"Authorize managed Tag Manager setup.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"authorizationUrl":{"type":"string","format":"uri","description":"Incremental Google authorization URL to open."}},"required":["authorizationUrl"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/integrations/google/gtm/preview":{"put":{"tags":["Integrations"],"operationId":"previewGoogleGtmChanges","summary":"Prepare and preview managed Tag Manager changes","description":"Creates or updates only Cursare-owned entities in an isolated workspace and returns their exact safe preview. The live container version is not changed. The GA4 destination must be a currently accessible discovered stream. Organization administrator only.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"ga4ResourceId":{"type":"string","minLength":1,"description":"Provider resource path of a GA4 web stream returned by discovery."}},"required":["ga4ResourceId"]}}}},"responses":{"200":{"description":"Prepare and preview managed Tag Manager changes.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"state":{"type":"string","enum":["not_connected","setup_required","connected","attention"],"description":"The derived connection state. Credentials are never included."},"connected":{"type":"boolean"},"identityEmail":{"description":"Safe email of the connected Google identity.","type":["string","null"]},"method":{"type":["string","null"],"enum":["direct_ga4","gtm"]},"active":{"type":"boolean"},"resource":{"type":["object","null"],"properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"]},"issueCode":{"type":["string","null"],"enum":["authorization_revoked","insufficient_scope","resource_unavailable","provider_unavailable"]},"grantedCapabilities":{"type":"object","properties":{"analyticsRead":{"type":"boolean"},"tagManagerRead":{"type":"boolean"},"tagManagerManage":{"type":"boolean"}},"required":["analyticsRead","tagManagerRead","tagManagerManage"]},"managedGtm":{"type":["object","null"],"properties":{"catalogVersion":{"type":"number","const":1,"description":"Canonical Cursare analytics catalog version."},"destination":{"type":"object","properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"],"description":"GA4 web stream that receives managed events."},"preview":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["tag","trigger","variable"]},"name":{"type":"string"},"action":{"type":"string","enum":["create","update"]}},"required":["kind","name","action"]}},"fingerprint":{"type":"string","minLength":64,"maxLength":64,"description":"Fingerprint of the exact pending preview."},"publishedAt":{"type":["string","null"],"format":"date-time"}},"required":["catalogVersion","destination","preview","fingerprint","publishedAt"]},"serverDelivery":{"type":"object","properties":{"configured":{"type":"boolean","description":"Whether encrypted GA4 Measurement Protocol credentials are configured."},"measurementId":{"description":"Safe GA4 measurement id. The API secret is never returned.","type":["string","null"]},"issueCode":{"type":["string","null"],"enum":["credentials_rejected","provider_unavailable"],"description":"Last actionable server-delivery health issue, if any."}},"required":["configured","measurementId","issueCode"]},"reporting":{"type":"object","properties":{"connected":{"type":"boolean","description":"Whether Analytics read access and a property are available."},"resource":{"type":["object","null"],"properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"],"description":"The GA4 web stream used for reports."},"issueCode":{"type":["string","null"],"enum":["authorization_revoked","insufficient_scope","resource_unavailable","provider_unavailable"],"description":"An Analytics reporting issue independent from browser and server delivery."},"revision":{"type":"string","description":"Changes whenever a reporting selection is replaced."}},"required":["connected","resource","issueCode","revision"]}},"required":["state","connected","identityEmail","method","active","resource","issueCode","grantedCapabilities","managedGtm","serverDelivery","reporting"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/integrations/google/gtm/publish":{"post":{"tags":["Integrations"],"operationId":"publishGoogleGtmChanges","summary":"Publish reviewed managed Tag Manager changes","description":"Creates and publishes a container version only when the submitted preview fingerprint still matches the saved Cursare workspace draft. Failed publication preserves the draft for retry. Organization administrator only.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"fingerprint":{"type":"string","minLength":64,"maxLength":64,"description":"Fingerprint returned with the administrator-reviewed draft."}},"required":["fingerprint"]}}}},"responses":{"200":{"description":"Publish reviewed managed Tag Manager changes.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"state":{"type":"string","enum":["not_connected","setup_required","connected","attention"],"description":"The derived connection state. Credentials are never included."},"connected":{"type":"boolean"},"identityEmail":{"description":"Safe email of the connected Google identity.","type":["string","null"]},"method":{"type":["string","null"],"enum":["direct_ga4","gtm"]},"active":{"type":"boolean"},"resource":{"type":["object","null"],"properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"]},"issueCode":{"type":["string","null"],"enum":["authorization_revoked","insufficient_scope","resource_unavailable","provider_unavailable"]},"grantedCapabilities":{"type":"object","properties":{"analyticsRead":{"type":"boolean"},"tagManagerRead":{"type":"boolean"},"tagManagerManage":{"type":"boolean"}},"required":["analyticsRead","tagManagerRead","tagManagerManage"]},"managedGtm":{"type":["object","null"],"properties":{"catalogVersion":{"type":"number","const":1,"description":"Canonical Cursare analytics catalog version."},"destination":{"type":"object","properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"],"description":"GA4 web stream that receives managed events."},"preview":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["tag","trigger","variable"]},"name":{"type":"string"},"action":{"type":"string","enum":["create","update"]}},"required":["kind","name","action"]}},"fingerprint":{"type":"string","minLength":64,"maxLength":64,"description":"Fingerprint of the exact pending preview."},"publishedAt":{"type":["string","null"],"format":"date-time"}},"required":["catalogVersion","destination","preview","fingerprint","publishedAt"]},"serverDelivery":{"type":"object","properties":{"configured":{"type":"boolean","description":"Whether encrypted GA4 Measurement Protocol credentials are configured."},"measurementId":{"description":"Safe GA4 measurement id. The API secret is never returned.","type":["string","null"]},"issueCode":{"type":["string","null"],"enum":["credentials_rejected","provider_unavailable"],"description":"Last actionable server-delivery health issue, if any."}},"required":["configured","measurementId","issueCode"]},"reporting":{"type":"object","properties":{"connected":{"type":"boolean","description":"Whether Analytics read access and a property are available."},"resource":{"type":["object","null"],"properties":{"accountId":{"type":"string","minLength":1},"accountName":{"type":"string","minLength":1},"resourceId":{"type":"string","minLength":1},"resourceName":{"type":"string","minLength":1},"publicId":{"type":"string","minLength":1}},"required":["accountId","accountName","resourceId","resourceName","publicId"],"description":"The GA4 web stream used for reports."},"issueCode":{"type":["string","null"],"enum":["authorization_revoked","insufficient_scope","resource_unavailable","provider_unavailable"],"description":"An Analytics reporting issue independent from browser and server delivery."},"revision":{"type":"string","description":"Changes whenever a reporting selection is replaced."}},"required":["connected","resource","issueCode","revision"]}},"required":["state","connected","identityEmail","method","active","resource","issueCode","grantedCapabilities","managedGtm","serverDelivery","reporting"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/integrations/whatsapp":{"put":{"tags":["Integrations"],"operationId":"connectWhatsappIntegration","summary":"Connect or replace WhatsApp credentials","description":"Validates and stores the organization's WhatsApp Cloud API credentials. Secrets are write-only. Organization administrator only.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"phoneNumberId":{"type":"string","minLength":1},"accessToken":{"type":"string","minLength":1},"notifyNumbers":{"maxItems":20,"type":"array","items":{"type":"string"}},"templateName":{"type":["string","null"]},"templateLanguage":{"type":["string","null"]}},"required":["phoneNumberId","accessToken","notifyNumbers"]}}}},"responses":{"200":{"description":"Connect or replace WhatsApp credentials.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"connected":{"type":"boolean"},"state":{"type":"string","enum":["not_connected","setup_required","connected","attention"],"description":"The derived connection state. Credentials are never included."},"phoneNumber":{"description":"Connected WhatsApp display number.","type":["string","null"]},"notifyNumbers":{"type":"array","items":{"type":"string"},"description":"Operational-notification recipients. An empty list disables staff notifications and allows a study-only connection."},"templateName":{"description":"Approved message template, when configured.","type":["string","null"]},"templateLanguage":{"description":"Configured template locale.","type":["string","null"]}},"required":["connected","state","phoneNumber","notifyNumbers","templateName","templateLanguage"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"tags":["Integrations"],"operationId":"deleteWhatsappIntegration","summary":"Disconnect WhatsApp","description":"Removes the WhatsApp connection and stops operational notifications without changing the Meta account. Organization administrator only.","responses":{"200":{"description":"Disconnect WhatsApp.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"deleted":{"type":"boolean","const":true}},"required":["deleted"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/integrations/whatsapp/credentials":{"put":{"tags":["Integrations"],"operationId":"replaceWhatsappCredentials","summary":"Replace WhatsApp credentials","description":"Validates and replaces the phone identity and encrypted access token without changing notification recipients or template settings. Organization administrator only.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"phoneNumberId":{"type":"string","minLength":1},"accessToken":{"type":"string","minLength":1}},"required":["phoneNumberId","accessToken"]}}}},"responses":{"200":{"description":"Replace WhatsApp credentials.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"connected":{"type":"boolean"},"state":{"type":"string","enum":["not_connected","setup_required","connected","attention"],"description":"The derived connection state. Credentials are never included."},"phoneNumber":{"description":"Connected WhatsApp display number.","type":["string","null"]},"notifyNumbers":{"type":"array","items":{"type":"string"},"description":"Operational-notification recipients. An empty list disables staff notifications and allows a study-only connection."},"templateName":{"description":"Approved message template, when configured.","type":["string","null"]},"templateLanguage":{"description":"Configured template locale.","type":["string","null"]}},"required":["connected","state","phoneNumber","notifyNumbers","templateName","templateLanguage"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/integrations/whatsapp/settings":{"patch":{"tags":["Integrations"],"operationId":"updateWhatsappSettings","summary":"Update WhatsApp notification settings","description":"Changes operational recipients and the approved template without asking for credentials again. Organization administrator only.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"notifyNumbers":{"maxItems":20,"type":"array","items":{"type":"string"}},"templateName":{"type":["string","null"]},"templateLanguage":{"type":["string","null"]}},"required":["notifyNumbers"]}}}},"responses":{"200":{"description":"Update WhatsApp notification settings.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"connected":{"type":"boolean"},"state":{"type":"string","enum":["not_connected","setup_required","connected","attention"],"description":"The derived connection state. Credentials are never included."},"phoneNumber":{"description":"Connected WhatsApp display number.","type":["string","null"]},"notifyNumbers":{"type":"array","items":{"type":"string"},"description":"Operational-notification recipients. An empty list disables staff notifications and allows a study-only connection."},"templateName":{"description":"Approved message template, when configured.","type":["string","null"]},"templateLanguage":{"description":"Configured template locale.","type":["string","null"]}},"required":["connected","state","phoneNumber","notifyNumbers","templateName","templateLanguage"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/integrations/whatsapp/test":{"post":{"tags":["Integrations"],"operationId":"testWhatsappIntegration","summary":"Send a real WhatsApp test notification","description":"Sends a real message to the configured recipients and reports provider failures. Organization administrator only.","responses":{"200":{"description":"Send a real WhatsApp test notification.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"sent":{"type":"boolean","const":true}},"required":["sent"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/integrations/video":{"delete":{"tags":["Integrations"],"operationId":"deleteVideoIntegration","summary":"Disconnect video hosting","description":"Removes credentials for new uploads. Existing provider videos remain untouched. Organization administrator only.","responses":{"200":{"description":"Disconnect video hosting.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"deleted":{"type":"boolean","const":true}},"required":["deleted"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/integrations/video/uploads":{"post":{"tags":["Integrations"],"operationId":"createVideoUpload","summary":"Create a direct video upload","description":"Creates a one-time provider upload URL. Video bytes travel from the browser to the configured provider and never pass through Cursare.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"maxDurationSeconds":{"type":"integer","minimum":1,"maximum":21600}}}}}},"responses":{"201":{"description":"Create a direct video upload.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"uploadURL":{"type":"string","format":"uri","description":"One-time provider upload URL."},"uid":{"type":"string","description":"Provider upload identifier used to resolve playback."},"method":{"type":"string","enum":["POST","PUT"],"description":"HTTP method required by the provider upload URL."}},"required":["uploadURL","uid","method"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/integrations/payments":{"delete":{"tags":["Integrations"],"operationId":"deletePaymentIntegration","summary":"Disconnect payments","description":"Removes the active payment connection. Paid checkout stops until a new provider is connected. Organization administrator only.","responses":{"200":{"description":"Disconnect payments.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"deleted":{"type":"boolean","const":true}},"required":["deleted"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/mcp/connections":{"get":{"tags":["MCP"],"operationId":"listMcpConnections","summary":"List MCP connections for the organization","description":"Lists organization-bound OAuth grants and dedicated headless API keys without tokens, hashes, or client secrets. Organization administrator only.","responses":{"200":{"description":"List MCP connections for the organization.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"oauth"},"clientId":{"type":"string","description":"OAuth client id of the connected assistant."},"clientName":{"type":"string","description":"Safe assistant display name."},"userId":{"type":"string","description":"Organization member who authorized the connection."},"userName":{"type":"string","description":"Safe member display name."},"scopes":{"type":"array","items":{"type":"string"},"description":"Granted OAuth authority."},"connectedAt":{"type":"string","format":"date-time"},"active":{"type":"boolean","description":"Whether this organization-bound grant can still be used."}},"required":["kind","clientId","clientName","userId","userName","scopes","connectedAt","active"]},{"type":"object","properties":{"kind":{"type":"string","const":"api_key"},"keyId":{"type":"string","description":"Dedicated API key id."},"clientName":{"type":"string","description":"Headless client selected during setup."},"userId":{"description":"Member who created the credential, when retained.","type":["string","null"]},"userName":{"description":"Safe creator display name, when retained.","type":["string","null"]},"prefix":{"type":"string","description":"Non-secret credential prefix."},"createdAt":{"type":"string","format":"date-time"},"lastUsedAt":{"type":["string","null"],"format":"date-time"},"expiresAt":{"type":["string","null"],"format":"date-time"},"state":{"type":"string","enum":["active","expired","revoked"]}},"required":["kind","keyId","clientName","userId","userName","prefix","createdAt","lastUsedAt","expiresAt","state"]}]}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/mcp/connections/{clientId}/{userId}":{"delete":{"tags":["MCP"],"operationId":"revokeMcpConnection","summary":"Revoke one organization-bound MCP connection","description":"Revokes only the assistant, member, and current organization tuple. Grants for other organizations remain active. Organization administrator only.","parameters":[{"name":"clientId","in":"path","required":true,"description":"OAuth client id of the assistant.","schema":{"type":"string"}},{"name":"userId","in":"path","required":true,"description":"Organization member who authorized it.","schema":{"type":"string"}}],"responses":{"200":{"description":"Revoke one organization-bound MCP connection.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"clientId":{"type":"string"},"userId":{"type":"string"},"revoked":{"type":"boolean","const":true}},"required":["clientId","userId","revoked"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/audit-events":{"get":{"tags":["Organization"],"operationId":"listAuditEvents","summary":"List audit events","description":"The organization's administrative trail, newest first — who did what, when. This is what answers “what changed in my org this week?”: course publishes and deletions, price and offer changes, learner grants and removals, refunds, team and member changes, integration connects and disconnects. Org-admin only. Read-only: events are written by the actions themselves and cannot be edited through the API. Use the export endpoint when the requested period is outside recent history.","parameters":[{"name":"since","in":"query","description":"Only events at or after this instant — this is how you scope to a period (`since` = 7 days ago answers “what changed this week?”). Omit for the whole trail.","schema":{"type":"string","format":"date-time"}},{"name":"until","in":"query","description":"Only events at or before this instant.","schema":{"type":"string","format":"date-time"}},{"name":"cursor","in":"query","description":"Opaque continuation cursor returned by the previous page. Do not construct or modify it.","schema":{"type":"string","minLength":1}},{"name":"limit","in":"query","description":"How many events to return, newest first. Applied AFTER `since`/`until`, so a full page back means the window holds more — narrow it and read again.","schema":{"default":50,"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"List audit events.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Stable audit event identifier."},"action":{"type":"string","description":"Cataloged administrative action key."},"actorUserId":{"description":"Current actor identity. Null means system or a deleted actor.","type":["string","null"]},"actorName":{"description":"Current display name resolved separately from the stored event.","type":["string","null"]},"targetId":{"description":"Primary affected resource identity, when the action has one.","type":["string","null"]},"detail":{"type":"object","properties":{},"additionalProperties":{},"description":"Bounded, action-specific non-personal context for the event."},"createdAt":{"type":"string","format":"date-time","description":"UTC instant when the successful command completed."}},"required":["id","action","actorUserId","actorName","targetId","detail","createdAt"]},"description":"Newest-first recent audit events for the authorized organization."},"nextCursor":{"description":"Opaque cursor for the next older page, or null when the page is final.","type":["string","null"]}},"required":["items","nextCursor"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/audit-events/export":{"get":{"tags":["Organization"],"operationId":"exportAuditEvents","summary":"Export audit history","description":"Streams the authorized organization's verified audit history as JSON Lines for a required date range. The stream merges archived and recent events exactly once and never exposes private storage paths, provider URLs, credentials, actor profile snapshots, or secrets. Organization owner or admin only.","parameters":[{"name":"since","in":"query","required":true,"description":"Inclusive UTC start instant for the required export range.","schema":{"type":"string","format":"date-time"}},{"name":"until","in":"query","required":true,"description":"Exclusive UTC end instant for the required export range.","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Export audit history.","content":{"application/x-ndjson":{"schema":{"type":"string","description":"A streaming JSON Lines document with one versioned, tenant-scoped audit event per line."}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api-keys":{"get":{"tags":["Organization"],"operationId":"listApiKeys","summary":"List API keys","description":"The org's live (non-revoked) developer keys — never the secret itself, only its prefix, name and last-used time. Use it to audit which credentials exist and which have gone stale. To tell which row is the credential you are calling with, match `prefix` against the first 12 characters of your own bearer token; revoking that one cuts off the current session (see `revokeApiKey`). If you authenticated with an OAuth access token rather than a `cr_live_…` key, none of these rows is yours and revoking any of them cannot lock you out. New keys are minted in the dashboard (Settings → Developer → API keys) on purpose: a key grants full org-admin authority and outlives the session that created it, so it is not something an assistant issues.","responses":{"200":{"description":"List API keys.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"prefix":{"type":"string","description":"The key's visible prefix — enough to identify it, never the secret. It is the first 12 characters of the token itself (`cr_live_` plus four more), so a caller using a key can spot its own credential by comparing this to its bearer token."},"lastUsedAt":{"type":["string","null"],"format":"date-time","description":"Null = never used since it was minted."},"expiresAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","name","prefix","lastUsedAt","expiresAt","createdAt"]}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api-keys/{id}":{"delete":{"tags":["Organization"],"operationId":"revokeApiKey","summary":"Revoke an API key","description":"Immediately and permanently disables the key — every integration still using it starts getting 401s on the next request. There is no un-revoke. Confirm with the operator which key is safe to kill (check `lastUsedAt` from `listApiKeys`) before calling this; revoking the key that authenticates the current session will end it.","parameters":[{"name":"id","in":"path","required":true,"description":"The API key id (from `listApiKeys`) — not the secret.","schema":{"type":"string"}}],"responses":{"200":{"description":"Revoke an API key.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"revoked":{"type":"boolean","const":true}},"required":["id","revoked"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/webhooks":{"get":{"tags":["Webhooks"],"operationId":"listWebhooks","summary":"List webhooks","description":"The org's outgoing webhook endpoints. Signing secrets are never included — the `whsec_` secret is returned exactly once, by the create call.","responses":{"200":{"description":"List webhooks.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string","description":"The https endpoint deliveries are POSTed to."},"events":{"type":"array","items":{"type":"string","enum":["enrollment.created","enrollment.requested","enrollment.approved","enrollment.rejected","enrollment.expired","learner.unenrolled","content.completed","content.created","content.updated","content.published","content.deleted","offer.created","offer.updated","offer.primary_changed","offer.archived","review.created","review.updated","cohort.created","cohort.updated","cohort.deleted","cohort.joined","cohort.member.moved","cohort.member.removed","discussion.post.created","discussion.post.deleted","discussion.post.resolved","discussion.post.reopened","purchase.created","purchase.installment.paid","purchase.installment.failed","purchase.installment.recovered","purchase.installment.canceled","campaign.redeemed","purchase.refunded","purchase.fee.updated"],"description":"An event key a webhook can subscribe to."},"description":"The events this endpoint subscribes to."},"active":{"type":"boolean","description":"Inactive endpoints receive no deliveries."},"teamId":{"description":"The owning team, or null for an org-level endpoint.","type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}},"required":["id","url","events","active","teamId","createdAt"]}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"tags":["Webhooks"],"operationId":"createWebhook","summary":"Create a webhook","description":"Registers an endpoint for signed event deliveries. The URL must be a public https host — localhost, private, and internal addresses are rejected. The response includes the `whsec_` signing secret ONCE; store it now, it is never shown again.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"events":{"minItems":1,"type":"array","items":{"type":"string","enum":["enrollment.created","enrollment.requested","enrollment.approved","enrollment.rejected","enrollment.expired","learner.unenrolled","content.completed","content.created","content.updated","content.published","content.deleted","offer.created","offer.updated","offer.primary_changed","offer.archived","review.created","review.updated","cohort.created","cohort.updated","cohort.deleted","cohort.joined","cohort.member.moved","cohort.member.removed","discussion.post.created","discussion.post.deleted","discussion.post.resolved","discussion.post.reopened","purchase.created","purchase.installment.paid","purchase.installment.failed","purchase.installment.recovered","purchase.installment.canceled","campaign.redeemed","purchase.refunded","purchase.fee.updated"]}},"teamId":{"type":["string","null"],"minLength":1}},"required":["url","events"]}}}},"responses":{"201":{"description":"Create a webhook.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string","description":"The https endpoint deliveries are POSTed to."},"events":{"type":"array","items":{"type":"string","enum":["enrollment.created","enrollment.requested","enrollment.approved","enrollment.rejected","enrollment.expired","learner.unenrolled","content.completed","content.created","content.updated","content.published","content.deleted","offer.created","offer.updated","offer.primary_changed","offer.archived","review.created","review.updated","cohort.created","cohort.updated","cohort.deleted","cohort.joined","cohort.member.moved","cohort.member.removed","discussion.post.created","discussion.post.deleted","discussion.post.resolved","discussion.post.reopened","purchase.created","purchase.installment.paid","purchase.installment.failed","purchase.installment.recovered","purchase.installment.canceled","campaign.redeemed","purchase.refunded","purchase.fee.updated"],"description":"An event key a webhook can subscribe to."},"description":"The events this endpoint subscribes to."},"active":{"type":"boolean","description":"Inactive endpoints receive no deliveries."},"teamId":{"description":"The owning team, or null for an org-level endpoint.","type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"secret":{"type":"string","description":"The `whsec_` HMAC signing secret — returned only in this response."}},"required":["id","url","events","active","teamId","createdAt","secret"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/webhooks/{id}":{"patch":{"tags":["Webhooks"],"operationId":"updateWebhook","summary":"Enable or disable a webhook","description":"Only `active` can change — an inactive endpoint keeps its configuration and delivery history but receives nothing. To change the URL or events, delete the webhook and create a new one.","parameters":[{"name":"id","in":"path","required":true,"description":"The webhook id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"active":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Enable or disable a webhook.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string","description":"The https endpoint deliveries are POSTed to."},"events":{"type":"array","items":{"type":"string","enum":["enrollment.created","enrollment.requested","enrollment.approved","enrollment.rejected","enrollment.expired","learner.unenrolled","content.completed","content.created","content.updated","content.published","content.deleted","offer.created","offer.updated","offer.primary_changed","offer.archived","review.created","review.updated","cohort.created","cohort.updated","cohort.deleted","cohort.joined","cohort.member.moved","cohort.member.removed","discussion.post.created","discussion.post.deleted","discussion.post.resolved","discussion.post.reopened","purchase.created","purchase.installment.paid","purchase.installment.failed","purchase.installment.recovered","purchase.installment.canceled","campaign.redeemed","purchase.refunded","purchase.fee.updated"],"description":"An event key a webhook can subscribe to."},"description":"The events this endpoint subscribes to."},"active":{"type":"boolean","description":"Inactive endpoints receive no deliveries."},"teamId":{"description":"The owning team, or null for an org-level endpoint.","type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}},"required":["id","url","events","active","teamId","createdAt"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"tags":["Webhooks"],"operationId":"deleteWebhook","summary":"Delete a webhook","description":"Removes the endpoint and its delivery history.","parameters":[{"name":"id","in":"path","required":true,"description":"The webhook id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Delete a webhook.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"deleted":{"type":"boolean","const":true}},"required":["id","deleted"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/webhooks/{id}/deliveries":{"get":{"tags":["Webhooks"],"operationId":"listWebhookDeliveries","summary":"List recent deliveries","description":"The endpoint's most recent delivery attempts, newest first.","parameters":[{"name":"id","in":"path","required":true,"description":"The webhook id.","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"default":20,"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"List recent deliveries.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"eventId":{"description":"Stable domain event id, or null for a manual `webhook.test` delivery.","type":["string","null"]},"event":{"type":"string","description":"The event that triggered the delivery (`webhook.test` for manual pings)."},"eventVersion":{"type":"integer","minimum":1,"description":"Version of the event payload contract."},"attempt":{"type":"integer","minimum":1,"description":"Attempt number for this event and endpoint."},"success":{"type":"boolean","description":"True when the endpoint answered 2xx within the timeout."},"responseStatus":{"type":["integer","null"],"description":"HTTP status the endpoint returned, or null if the request never completed."},"error":{"description":"Network/timeout error message, or null when an HTTP response came back.","type":["string","null"]},"durationMs":{"type":"integer","description":"Round-trip time of the delivery attempt, in milliseconds."},"requestBody":{"type":"string","description":"The signed JSON body that was POSTed (truncated)."},"responseBody":{"description":"The endpoint's response body (truncated).","type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}},"required":["id","eventId","event","eventVersion","attempt","success","responseStatus","error","durationMs","requestBody","responseBody","createdAt"]}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/webhooks/{id}/test":{"post":{"tags":["Webhooks"],"operationId":"testWebhook","summary":"Send a test ping","description":"POSTs a signed `webhook.test` event to the endpoint and records the attempt. Returns 200 even if the endpoint fails — check the delivery log for the result.","parameters":[{"name":"id","in":"path","required":true,"description":"The webhook id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Send a test ping.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"sent":{"type":"boolean","const":true}},"required":["id","sent"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/openapi.json":{"get":{"tags":["Index"],"operationId":"getOpenApiSpec","summary":"This OpenAPI document","description":"The machine-readable OpenAPI 3.1 description of this API. Public — no auth.","security":[],"responses":{"200":{"description":"The OpenAPI 3.1 document.","content":{"application/json":{"schema":{"type":"object"}}}}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"Organization API key","description":"An organization API key (`cr_live_…`) from Settings → Developer → API keys."},"learnerToken":{"type":"http","scheme":"bearer","bearerFormat":"Short-lived learner runtime token","description":"A browser-safe learner token returned by POST /learner-runtime/sessions."}},"responses":{"BadRequest":{"description":"Validation failed or the request body is malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"Missing, invalid or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The key's organization does not own this resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"The resource does not exist (or belongs to another org).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"TooManyRequests":{"description":"Rate limit exceeded (240 reads/min, 60 writes/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InternalError":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string","description":"A human-readable error message."},"reason":{"description":"A stable machine-readable validation category when available.","type":"string"},"details":{"description":"Structured profile paths, readiness issues, or field context when available."}},"required":["error"]},"Organization":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"slug":{"type":["string","null"]},"cover":{"description":"Banner image on the org's public storefront. Null when none is set.","type":["string","null"]},"requireCheckoutTaxId":{"type":"boolean","description":"Whether buyers must enter a tax id to complete checkout."},"usage":{"type":"object","properties":{"contents":{"type":"integer","description":"Contents with enrollment stats."},"enrollments":{"type":"integer"},"revenue":{"type":"integer","description":"Rough size signal ONLY — do NOT report it as an amount of money. It adds up the minor units of EVERY currency the org sells in with no conversion, so on a multi-currency org it is a meaningless number (1000 BRL + 1000 USD reads as 2000, and currencies with different decimal places are mixed in too). It is net of refunds. For a figure you can quote, use `listSales` (`revenueByCurrency`) or, for what actually settled, `getPayouts`."}},"required":["contents","enrollments","revenue"]}},"required":["id","name","slug","cover","requireCheckoutTaxId","usage"]},"Content":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["learning","article"],"description":"Learning content can be offered; an article publishes on its owner's profile."},"routeSegment":{"type":"string","description":"Stable URL segment, unique inside the organization; it does not imply access."},"title":{"type":"string"},"description":{"type":["string","null"]},"isPublished":{"type":"boolean","description":"Whether learners have a published document to read."},"hasUnpublishedChanges":{"type":"boolean","description":"Whether a published content has document edits that learners cannot see yet."},"tags":{"type":"array","items":{"type":"string"}},"theme":{"description":"Accent theme used by learner-facing content.","type":["string","null"]},"certificateTheme":{"type":"string","enum":["classic","modern","editorial","minimal"],"description":"Certificate layout selected by the content creator."},"teamId":{"type":["string","null"]},"ownerId":{"type":["string","null"]},"publishedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","kind","routeSegment","title","description","isPublished","hasUnpublishedChanges","tags","theme","certificateTheme","teamId","ownerId","publishedAt","createdAt","updatedAt"],"description":"Editorial identity, publication, discovery, and ownership of a content."},"ContentLearner":{"type":"object","properties":{"userId":{"type":"string"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"doneSteps":{"type":"integer"},"totalSteps":{"type":"integer"},"completed":{"type":"boolean"},"lastQuiz":{"type":["object","null"],"properties":{"score":{"type":"integer"},"total":{"type":"integer"}},"required":["score","total"],"description":"The learner's most recent quiz attempt, if any."},"enrolledAt":{"type":"string","format":"date-time"},"accessStartsAt":{"type":"string","format":"date-time"},"accessEndsAt":{"type":["string","null"],"format":"date-time"}},"required":["userId","name","email","doneSteps","totalSteps","completed","lastQuiz","enrolledAt","accessStartsAt","accessEndsAt"],"description":"A roster entry for one content, with progress."},"Learner":{"type":"object","properties":{"id":{"type":"string","description":"The enrollment id."},"userId":{"type":"string"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"contentId":{"type":"string"},"contentSlug":{"type":"string"},"doneSteps":{"type":"integer"},"totalSteps":{"type":"integer"},"completed":{"type":"boolean"},"completedAt":{"type":["string","null"],"format":"date-time"},"enrolledAt":{"type":"string","format":"date-time"},"accessStartsAt":{"type":"string","format":"date-time"},"accessEndsAt":{"type":["string","null"],"format":"date-time"}},"required":["id","userId","name","email","contentId","contentSlug","doneSteps","totalSteps","completed","completedAt","enrolledAt","accessStartsAt","accessEndsAt"],"description":"One enrollment (a user on a content) from the org-wide list."},"Tag":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"usageCount":{"type":"integer","description":"How many contents carry the tag (list responses only)."}},"required":["id","name","description"]},"Campaign":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"offerIds":{"type":["array","null"],"items":{"type":"string"},"description":"The paid offers this campaign is scoped to; null (or empty) = global (org-wide, every paid offer)."},"percentOff":{"type":["integer","null"]},"amountOff":{"type":["integer","null"],"description":"Discount in the currency's minor unit (cents)."},"maxRedemptions":{"type":["integer","null"]},"redemptions":{"type":"integer"},"active":{"type":"boolean"},"public":{"type":"boolean","description":"Public campaigns advertise a de/por price on the storefront."},"image":{"description":"Optional promo banner image URL.","type":["string","null"]},"disclaimer":{"description":"Optional fine print shown with the public promo.","type":["string","null"]},"expiresAt":{"format":"date-time","description":"ISO date-time after which the code stops applying; null = no expiry.","type":["string","null"]}},"required":["id","code","offerIds","percentOff","amountOff","maxRedemptions","redemptions","active","public","image","disclaimer","expiresAt"]},"Team":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"logo":{"type":["string","null"]},"members":{"type":"array","items":{"$ref":"#/components/schemas/TeamMember"}}},"required":["id","name","logo","members"]},"TeamMember":{"type":"object","properties":{"userId":{"type":"string"},"name":{"type":"string"},"email":{"type":"string","format":"email"}},"required":["userId","name","email"]},"Sales":{"type":"object","properties":{"revenueByCurrency":{"type":"object","additionalProperties":{"type":"integer"},"description":"Revenue excluding refunded purchases per ISO currency code, in minor units."},"totalPurchases":{"type":"integer"},"byContent":{"type":"array","items":{"type":"object","properties":{"contentId":{"type":"string"},"slug":{"type":["string","null"]},"currency":{"type":"string"},"purchases":{"type":"integer"},"revenue":{"type":"integer","description":"Revenue excluding refunded purchases in the currency's minor unit (cents)."}},"required":["contentId","slug","currency","purchases","revenue"]}}},"required":["revenueByCurrency","totalPurchases","byContent"]},"Insights":{"type":"object","properties":{"academic":{"type":"object","properties":{"enrollments":{"type":"integer"},"completions":{"type":"integer"},"completionRate":{"type":"integer","description":"Percentage, 0–100."},"quizAttempts":{"type":"integer"},"avgQuizScore":{"type":["integer","null"],"description":"Average quiz score as a percentage; null with no scored attempts."}},"required":["enrollments","completions","completionRate","quizAttempts","avgQuizScore"]},"financial":{"type":"object","properties":{"revenue":{"type":"integer","description":"Rough size signal ONLY — do NOT report it as an amount of money. It adds up the minor units of EVERY currency the org sells in with no conversion, so on a multi-currency org it is a meaningless number (1000 BRL + 1000 USD reads as 2000, and currencies with different decimal places are mixed in too). It is net of refunds. For a figure you can quote, use `listSales` (`revenueByCurrency`) or, for what actually settled, `getPayouts`."},"purchases":{"type":"integer"}},"required":["revenue","purchases"]}},"required":["academic","financial"]}}}}