{"openapi":"3.0.3","security":[{"accessKey":[]}],"info":{"title":"Retorio API","version":"1.0.0","description":"Every endpoint a Retorio integration calls: managing cohorts and the users in them, configuring\nwebhooks, and the single sign-on calls the coaching app makes. The base URL is\n`https://api.retorio.com/be/v2`.\n\nAuthentication, the errors every endpoint shares and a guide for each topic: [Getting started](https://docs.retorio.com/)."},"tags":[{"name":"Cohorts","description":"Coaching users in Retorio are organized in cohorts, each permanently either `email` (invited by address) or `token` (invited with a generated, anonymous access token handed to the coaching user directly). These endpoints create and manage cohorts, and invite, list, disable, and remove the people in them."},{"name":"Webhooks","description":"Configure outbound event delivery to your own systems. Delivery, signatures and retries: [Webhooks](https://docs.retorio.com/webhooks/). The request and response shapes below cover configuring and inspecting webhooks themselves."},{"name":"Single sign-on","description":"The SSO endpoints of this API, called by the Retorio coaching app during sign-in and sign-up, not by an integration. The end-to-end flow and how to set it up: [Single sign-on](https://docs.retorio.com/sso/)."}],"x-tagGroups":[{"name":"Integration","tags":["Cohorts","Webhooks","Single sign-on"]}],"components":{"schemas":{"CohortType":{"type":"string","enum":["email","token"]},"OrganizationWebhookDeliveryStatus":{"type":"string","enum":["pending","succeeded","failed","cancelled"]},"languageEnum":{"type":"string","enum":["en-US","fr-FR","de-DE","es-ES","it-IT","pt-PT","cs-CZ","ru-RU","el-GR","nl-NL","bg-BG","ko-KR","tr-TR","pl-PL"]},"scenarioStatusCounts":{"type":"object","properties":{"unpublished":{"type":"integer","minimum":0},"publishing":{"type":"integer","minimum":0},"published":{"type":"integer","minimum":0}},"required":["unpublished","publishing","published"]},"appErrorResponse":{"type":"object","properties":{"message":{"type":"string"},"status":{"type":"string","description":"Canonical error name, e.g. `INVALID_ARGUMENT`."},"details":{"nullable":true}},"required":["message","status"]},"httpExceptionResponse":{"type":"object","properties":{"statusCode":{"type":"integer"},"message":{"type":"string"},"error":{"type":"string","description":"The HTTP reason phrase, e.g. `Bad Request`."}},"required":["statusCode","message","error"]},"coachingProductMissingResponse":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]},"authDetailsEntity":{"type":"object","properties":{"organizationName":{"type":"string","minLength":1,"maxLength":255},"organizationExtId":{"type":"string","minLength":1,"maxLength":255},"companyName":{"type":"string","minLength":1,"maxLength":255},"logoUrl":{"type":"string","nullable":true,"minLength":1,"maxLength":255,"default":null},"samlProviderId":{"type":"string","nullable":true,"minLength":1,"maxLength":255,"default":null},"tenantId":{"type":"string","nullable":true,"minLength":1,"maxLength":255,"default":null},"SSOType":{"anyOf":[{"type":"string","enum":["google","microsoft","saml","oidc"]},{"type":"string","enum":["email"]}]}},"required":["organizationName","organizationExtId","companyName","SSOType"]},"updateUserStatusEndpoint":{"type":"object","properties":{"isDisabled":{"type":"boolean"}},"required":["isDisabled"],"additionalProperties":false},"addNewEmailsEndpoint":{"type":"object","properties":{"emails":{"type":"array","items":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[A-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[A-Z0-9.-]+\\.[A-Z]{2,}$/i"},"minItems":1,"maxItems":200,"description":"List of emails to invite into cohort","example":["maria.schmidt@customer.example","j.tan@customer.example"]},"language":{"$ref":"#/components/schemas/languageEnum"}},"required":["emails","language"],"additionalProperties":false},"userExtIdsList":{"type":"object","properties":{"userExtIds":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":200,"description":"List of user ext ids","example":["6f1c0a2e_9b41_4d0c_8a7e_2f5b8c1d0e93"]}},"required":["userExtIds"],"additionalProperties":false},"cohortParticipantResponse":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"userId":{"type":"string","description":"The participant's user ext id."},"token":{"type":"string","nullable":true,"maxLength":10,"description":"The user's access token in a `token` cohort, `null` in an `email` cohort."},"status":{"type":"string","nullable":true,"enum":["USED","RESERVED","AVAILABLE",null],"description":"`USED` once the token is redeemed, `AVAILABLE` while it is not, and `RESERVED` for an unredeemed token held by a reservation that has not expired. `null` in an `email` cohort."}},"required":["createdAt","userId","token","status"]},"addCohortTokensRequestBody":{"type":"object","properties":{"numberTokens":{"type":"integer","minimum":1,"maximum":200,"description":"How many new tokens to generate, 1 to 200 per call.","example":25}},"required":["numberTokens"]},"emailParticipantResponse":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"profile":{"type":"object","additionalProperties":{"nullable":true},"nullable":true,"description":"The user's stored profile, or `null` when none is stored."},"email":{"type":"string","maxLength":255},"lastInvitedAt":{"type":"string","nullable":true,"format":"date-time"},"isDisabled":{"type":"boolean"},"userId":{"type":"string","description":"The user's ext id."},"cohortExtId":{"type":"string","nullable":true,"description":"The cohort of this membership, `null` once that cohort is deleted."},"cohortName":{"type":"string","nullable":true,"description":"The cohort name, `null` once that cohort is deleted."},"state":{"type":"string","enum":["ACTIVATED","INVITED","DISABLED","REMOVED"],"description":"`REMOVED` when this membership was removed, otherwise `DISABLED` for a disabled user, `ACTIVATED` once the user has signed up, and `INVITED` before that."},"participantId":{"type":"string","description":"The membership's ext id."}},"required":["createdAt","email","lastInvitedAt","isDisabled","userId","cohortExtId","cohortName","state","participantId"]},"resendEmailsBatchResponse":{"type":"object","properties":{"sent":{"type":"integer","description":"How many invitation emails this call sent."},"remaining":{"type":"integer","description":"How many users in the cohort are still eligible for a resend. Call again until it is `0`."}},"required":["sent","remaining"]},"resendPreviewResponse":{"type":"object","properties":{"cohorts":{"type":"array","items":{"type":"object","properties":{"extId":{"type":"string","maxLength":64},"name":{"type":"string","maxLength":255},"emails":{"type":"array","items":{"type":"string"},"description":"The addresses a resend in this cohort would reach now, in alphabetical order."}},"required":["extId","name","emails"]}}},"required":["cohorts"]},"createCohortRequestBody":{"type":"object","properties":{"name":{"type":"string","minLength":3,"description":"The name of the cohort.","example":"Sales onboarding 2026"},"type":{"allOf":[{"$ref":"#/components/schemas/CohortType"},{"description":"Fixed at creation and never changes. An `email` cohort is invited by address. A `token` cohort is invited with a generated, anonymous access token."}]},"isForBenchmarking":{"type":"boolean","description":"Whether this cohort is used for benchmark profiling. Programs are assigned to it like any other cohort, and its coaching users’ attempts in them feed the benchmark profiles."}},"required":["name","type"]},"updateCohortRequestBody":{"type":"object","properties":{"name":{"type":"string","minLength":3,"description":"The new name of the cohort.","example":"Sales onboarding 2027"}},"required":["name"]},"cohortResponse":{"type":"object","properties":{"extId":{"type":"string","maxLength":64},"name":{"type":"string","maxLength":255},"createdAt":{"type":"string","format":"date-time"}},"required":["extId","name","createdAt"]},"cohortWithDetailsResponse":{"allOf":[{"$ref":"#/components/schemas/cohortResponse"},{"type":"object","properties":{"isForBenchmarking":{"type":"boolean"},"type":{"$ref":"#/components/schemas/CohortType"},"participants":{"type":"integer","description":"Total participants in the cohort."},"activeTokens":{"type":"integer","description":"Generated tokens already redeemed by a coaching user."},"availableTokens":{"type":"integer","description":"Generated tokens not yet redeemed."},"programs":{"type":"integer","description":"How many programs the cohort has assigned, whatever each assignment’s period (an `upcoming` or `finished` assignment counts, an unassigned one does not). Always present on `GET /cohorts/{id}`. On `GET /cohorts` it is present only with `includeRecordingSessions=true`."},"recordingSessions":{"type":"integer","description":"Attempts with a result, not deleted, made through the cohort's current program assignments. Only `GET /cohorts?includeRecordingSessions=true` computes it. It is `0` everywhere else, including `GET /cohorts/{id}`."},"activeEmails":{"type":"integer","description":"Email-invited users who have completed registration."}},"required":["isForBenchmarking","type","participants","activeTokens","availableTokens","recordingSessions","activeEmails"]}]},"createCohortProgramsRequestBody":{"type":"object","properties":{"startDate":{"type":"string","description":"When every assigned program becomes visible to the cohort.","example":"2026-12-01T00:00:00.000Z"},"endDate":{"type":"string","nullable":true,"description":"When the assigned programs stop accepting new attempts. A coaching user keeps seeing an ended assignment they have attempts in. Omit or send `null` for no end date.","example":"2027-03-31T23:59:59.000Z"},"programExtIds":{"type":"array","items":{"type":"string"},"description":"Programs to assign, by ext id. A program already holding a live assignment in this cohort fails the whole call. Unassign it first to re-assign with a new period.","example":["3c9a7e15_8d42_4b6f_a1e0_5f2d9c8b7a64"]}},"required":["startDate","programExtIds"]},"updateCohortProgramRequestBody":{"type":"object","properties":{"startDate":{"type":"string","example":"2026-12-01T00:00:00.000Z"},"endDate":{"type":"string","nullable":true,"example":"2027-03-31T23:59:59.000Z"}},"required":["startDate","endDate"]},"updateCohortProgramsOrderRequestBody":{"type":"array","items":{"type":"object","properties":{"extId":{"type":"string","description":"The cohort-program assignment ext id.","example":"e90f3b7c_1a26_44d5_b8c1_0d94e7f25a63"},"order":{"type":"integer","example":0}},"required":["extId","order"]},"minItems":1,"description":"Every assignment currently in the cohort, once each, with its new `order` (`0` to `n - 1`). An unknown or repeated ext id, a wrong number of entries, or `order` values that are not exactly `0` to `n - 1` (a gap or a repeat) fail the whole call."},"cohortProgramResponse":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"extId":{"type":"string","maxLength":64},"startDate":{"type":"string","format":"date-time"},"endDate":{"type":"string","nullable":true,"format":"date-time"},"order":{"type":"integer"},"programId":{"type":"string","description":"The assigned program's ext id."},"title":{"type":"string","description":"The assigned program's title."},"scenarioStatusCounts":{"allOf":[{"$ref":"#/components/schemas/scenarioStatusCounts"},{"description":"The program's non-deleted scenarios grouped by publish status, always carrying all three keys even when a count is zero."}]},"cohortProgramStatus":{"type":"string","enum":["upcoming","active","finished"],"description":"`upcoming` before `startDate`, `finished` once `endDate` has passed (never for an open-ended assignment, which has no `endDate`), `active` otherwise."}},"required":["createdAt","extId","startDate","endDate","order","programId","title","scenarioStatusCounts","cohortProgramStatus"]},"unusedCohortProgramResponse":{"type":"object","properties":{"id":{"type":"string","description":"The program's ext id."},"title":{"type":"string"}},"required":["id","title"]},"subscribableWebhookEventType":{"type":"string","enum":["coaching.result.available"]},"webhookUser":{"type":"object","properties":{"extId":{"type":"string","minLength":1,"maxLength":255},"identifierType":{"type":"string","enum":["email","token"]},"identifier":{"type":"string"}},"required":["extId","identifierType","identifier"],"additionalProperties":false},"coachingResultAvailableEventData":{"type":"object","properties":{"user":{"$ref":"#/components/schemas/webhookUser"},"cohort":{"type":"object","properties":{"extId":{"type":"string","minLength":1,"maxLength":255},"name":{"type":"string"}},"required":["extId","name"],"additionalProperties":false},"program":{"type":"object","properties":{"extId":{"type":"string","minLength":1,"maxLength":255},"name":{"type":"string"}},"required":["extId","name"],"additionalProperties":false},"scenario":{"type":"object","properties":{"extId":{"type":"string","minLength":1,"maxLength":255},"name":{"type":"string"}},"required":["extId","name"],"additionalProperties":false},"session":{"type":"object","properties":{"extId":{"type":"string","minLength":1,"maxLength":255},"createdAt":{"type":"string","format":"date-time"},"trainingTimeSeconds":{"type":"integer","nullable":true,"minimum":0},"practiceTimeSeconds":{"type":"integer","nullable":true,"minimum":0},"pausedTimeSeconds":{"type":"integer","nullable":true,"minimum":0},"overallScore":{"type":"number","minimum":0,"maximum":1}},"required":["extId","createdAt","trainingTimeSeconds","practiceTimeSeconds","pausedTimeSeconds","overallScore"],"additionalProperties":false}},"required":["user","cohort","program","scenario","session"],"additionalProperties":false},"webhookTestEventData":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false},"webhookEventEnvelope":{"oneOf":[{"type":"object","properties":{"version":{"type":"number","enum":[1]},"eventId":{"type":"string","minLength":1,"maxLength":255},"occurredAt":{"type":"string","format":"date-time"},"organization":{"type":"object","properties":{"extId":{"type":"string","minLength":1,"maxLength":255},"name":{"type":"string"}},"required":["extId","name"],"additionalProperties":false},"eventType":{"type":"string","enum":["coaching.result.available"]},"data":{"$ref":"#/components/schemas/coachingResultAvailableEventData"}},"required":["version","eventId","occurredAt","organization","eventType","data"],"additionalProperties":false},{"type":"object","properties":{"version":{"type":"number","enum":[1]},"eventId":{"type":"string","minLength":1,"maxLength":255},"occurredAt":{"type":"string","format":"date-time"},"organization":{"type":"object","properties":{"extId":{"type":"string","minLength":1,"maxLength":255},"name":{"type":"string"}},"required":["extId","name"],"additionalProperties":false},"eventType":{"type":"string","enum":["webhook.test"]},"data":{"$ref":"#/components/schemas/webhookTestEventData"}},"required":["version","eventId","occurredAt","organization","eventType","data"],"additionalProperties":false}]},"webhookCustomHeaderEntry":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[!#$%&'*+.^_`|~0-9A-Za-z-]+$","description":"A valid HTTP header name, unique within the set regardless of case. Names starting with `X-Retorio-` and these are reserved: `connection`, `content-encoding`, `content-length`, `content-type`, `expect`, `host`, `keep-alive`, `proxy-authenticate`, `proxy-authorization`, `te`, `trailer`, `transfer-encoding`, `upgrade`, `user-agent`.","example":"Authorization"},"value":{"type":"string","minLength":1,"maxLength":4096,"description":"The header value, sent exactly as given. At most 4096 characters of printable ASCII or tab, with no line breaks. Leave it out on an update to keep the value stored under this `name`, so a credential you cannot read back is kept. Leaving it out for a name that is not stored, or on create, is a `400`.","example":"Bearer <your endpoint token>"}},"required":["name"]},"createOrganizationWebhookRequestBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"description":"Shown in the webhook list. Must contain at least one letter, digit, punctuation mark or symbol.","example":"CRM sync"},"url":{"type":"string","maxLength":2048,"pattern":"^https:\\/\\/","description":"Your endpoint. It must use `https`, be at most 2048 characters and carry no credentials (no user name or password).","example":"https://hooks.customer.example/retorio"},"subscribedEvents":{"type":"array","items":{"$ref":"#/components/schemas/subscribableWebhookEventType"},"minItems":1},"customHeaders":{"type":"array","items":{"$ref":"#/components/schemas/webhookCustomHeaderEntry"},"maxItems":10,"description":"At most 10 headers, sent with every delivery. Together they may take at most 8192 bytes, counting each as `<name>: <value>\\r\\n`, stored values included."},"isEnabled":{"type":"boolean","default":true}},"required":["name","url","subscribedEvents"]},"updateOrganizationWebhookRequestBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"description":"Shown in the webhook list. Must contain at least one letter, digit, punctuation mark or symbol.","example":"CRM sync"},"url":{"type":"string","maxLength":2048,"pattern":"^https:\\/\\/","description":"Your endpoint. It must use `https`, be at most 2048 characters and carry no credentials (no user name or password).","example":"https://hooks.customer.example/retorio"},"subscribedEvents":{"type":"array","items":{"$ref":"#/components/schemas/subscribableWebhookEventType"},"minItems":1},"customHeaders":{"type":"array","items":{"$ref":"#/components/schemas/webhookCustomHeaderEntry"},"maxItems":10,"description":"At most 10 headers, sent with every delivery. Together they may take at most 8192 bytes, counting each as `<name>: <value>\\r\\n`, stored values included."},"rotateSigningSecret":{"type":"boolean","default":false},"isEnabled":{"type":"boolean"},"expectedLastChangedAt":{"type":"string","format":"date-time"}},"required":["name","url","subscribedEvents"]},"organizationWebhookResponse":{"type":"object","properties":{"extId":{"type":"string","maxLength":64},"isEnabled":{"type":"boolean"},"name":{"type":"string"},"url":{"type":"string"},"customHeaderNames":{"type":"array","items":{"type":"string"}},"customHeadersUnreadable":{"type":"boolean","description":"True when the stored custom headers cannot be decrypted, in which case `customHeaderNames` is empty. While it is true, every delivery to this webhook, the test event included, fails and is not retried. Repair it with an update that sends every header with its `value`, or `customHeaders: []`. An entry without a `value` cannot be kept from an unreadable set, and the update answers `400`."},"subscribedEvents":{"type":"array","items":{"$ref":"#/components/schemas/subscribableWebhookEventType"}},"lastChangedAt":{"type":"string","format":"date-time"},"lastChangedBy":{"type":"string"},"hasBeenEdited":{"type":"boolean"}},"required":["extId","isEnabled","name","url","customHeaderNames","customHeadersUnreadable","subscribedEvents","lastChangedAt","lastChangedBy","hasBeenEdited"]},"organizationWebhookWithSecretResponse":{"allOf":[{"$ref":"#/components/schemas/organizationWebhookResponse"},{"type":"object","properties":{"signingSecret":{"type":"string","description":"The secret that signs every delivery, returned only by create and by an update with `rotateSigningSecret: true`. The HMAC key is the full `signingSecret` string exactly as returned, `whsec_` prefix included, taken as UTF-8 bytes. Do not strip the prefix or base64-decode it."}}}]},"getOrganizationWebhooksResponse":{"type":"object","properties":{"organizationWebhooks":{"type":"array","items":{"$ref":"#/components/schemas/organizationWebhookResponse"}}},"required":["organizationWebhooks"]},"getOrganizationWebhookDeliveriesResponse":{"type":"object","properties":{"deliveries":{"type":"array","items":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"extId":{"type":"string","maxLength":64},"eventType":{"type":"string","maxLength":64},"status":{"$ref":"#/components/schemas/OrganizationWebhookDeliveryStatus"},"attemptCount":{"type":"integer"},"lastStatusCode":{"type":"integer","nullable":true},"lastError":{"type":"string","nullable":true},"deliveredAt":{"type":"string","nullable":true,"format":"date-time"}},"required":["createdAt","updatedAt","extId","eventType","status","attemptCount","lastStatusCode","lastError","deliveredAt"]}}},"required":["deliveries"]},"testOrganizationWebhookResponse":{"type":"object","properties":{"succeeded":{"type":"boolean"},"statusCode":{"type":"integer","nullable":true,"minimum":0},"error":{"type":"string","nullable":true}},"required":["succeeded","statusCode","error"]},"ssoSignup":{"type":"object","properties":{"displayedName":{"type":"string","nullable":true,"minLength":1,"maxLength":255,"default":null,"example":"Maria Schmidt"},"legalConsent":{"type":"boolean"},"privacyPolicyConsent":{"type":"boolean"},"contactConsent":{"type":"boolean"}},"required":["legalConsent","privacyPolicyConsent","contactConsent"]}},"parameters":{},"securitySchemes":{"accessKey":{"type":"http","scheme":"bearer","description":"An access key, sent as `Authorization: Bearer <access key>`. It acts as the admin who created it.","x-label":"Access key","x-link":"/authentication/"},"coachingUserToken":{"type":"http","scheme":"bearer","description":"The coaching user's own Retorio sign-in token, sent as `Authorization: Bearer <token>` and issued when they sign in through your identity provider. The Retorio coaching app calls this endpoint on their behalf; your integration does not call it.","x-label":"Coaching user's own token","x-link":"/sso/#how-sign-in-works"}}},"paths":{"/auth/auth_details":{"get":{"operationId":"getAuthDetails","summary":"Look up sign-in method for an organization","description":"Public, unauthenticated lookup used by a login page before the user has signed in: given an organization's name, it says whether that organization signs in by SSO or by email and password, and returns the organization and company name and the logo to render on the sign-in screen, plus, for an SSO organization, the tenant id and (for a SAML or OIDC provider) the provider id the login page starts sign-in with. The organization's privacy policy is not part of this response. This is a read of existing configuration. How single sign-on is set up: [Single sign-on](https://docs.retorio.com/sso/).","tags":["Single sign-on"],"security":[],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"example":"customer"},"required":true,"name":"organizationName","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/authDetailsEntity"}}}},"400":{"description":"`organizationName` is missing or not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"404":{"description":"No organization with this name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}}},"/auth/coaching_sso_signup":{"post":{"operationId":"coachingSsoSignup","summary":"Finalize sign-up for an SSO user","description":"Called by the coaching app after your identity provider authenticates an invited user who has not completed sign-up yet, to record their name and consent and mark them registered. When Retorio is configured to read the name from your IdP's attributes and the token carries one, that name is used instead of `displayedName`. `legalConsent` and `privacyPolicyConsent` must be `true`. A user whose invitation has expired is refused and must be invited again. The user itself already exists from the cohort invite. There is nothing for an integrator to call here directly: a user reaches this only by signing in through the coaching app once they have been invited into a cohort with the email their IdP asserts.","tags":["Single sign-on"],"security":[{"coachingUserToken":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ssoSignup"}}}},"responses":{"204":{"description":"Account finalized"},"400":{"description":"The request body is not valid (`legalConsent` and `privacyPolicyConsent` must be `true`), your organization does not have single sign-on enabled, or the user is already registered. Also answered when the request body is not valid JSON.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated. Also answered when a coaching user signing in by single sign-on has not completed sign-up and their invitation has expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to a coaching user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"413":{"description":"The request body is larger than 10 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"415":{"description":"The `Content-Type` charset or the `Content-Encoding` is one the API cannot decode. Send UTF-8 JSON without a content encoding.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}}},"/cohorts":{"get":{"operationId":"getCohorts","summary":"List cohorts","description":"Lists your organization's cohorts with aggregate participant and token counts. It is the usual first call before inviting or removing anyone, to find the cohort id and type you need.","tags":["Cohorts"],"x-required-permission":{"permission":"cohorts:view","label":"View cohorts, their programs and their members","systemRoles":["Owner","Admin"],"link":"/roles/#cohorts-view"},"parameters":[{"schema":{"type":"string","description":"`true` returns only benchmarking cohorts and any other non-empty value only the others. Absent or empty returns both."},"required":false,"description":"`true` returns only benchmarking cohorts and any other non-empty value only the others. Absent or empty returns both.","name":"includeBenchmarkingCohorts","in":"query"},{"schema":{"type":"string","description":"`true` adds `programs` to each cohort and computes `recordingSessions`. Any other value or none omits `programs` and leaves `recordingSessions` at `0`."},"required":false,"description":"`true` adds `programs` to each cohort and computes `recordingSessions`. Any other value or none omits `programs` and leaves `recordingSessions` at `0`.","name":"includeRecordingSessions","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/cohortWithDetailsResponse"}}}}},"400":{"description":"A query parameter is not valid, for example one sent more than once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or your organization does not have the coaching product, or the admin's roles do not grant `cohorts:view`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/coachingProductMissingResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}},"post":{"operationId":"createCohort","summary":"Create a cohort","description":"Creates an empty cohort. `type` is fixed for the lifetime of the cohort: create an `email` cohort to invite users by address, or a `token` cohort to generate anonymous access tokens.","tags":["Cohorts"],"x-required-permission":{"permission":"cohorts:manage","label":"Create, edit and delete cohorts, and assign programs to them","systemRoles":["Owner","Admin"],"link":"/roles/#cohorts-manage"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/createCohortRequestBody"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/cohortResponse"}}}},"400":{"description":"The request body is not valid. Also answered when the request body is not valid JSON.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or your organization does not have the coaching product, or the admin's roles do not grant `cohorts:manage`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/coachingProductMissingResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"413":{"description":"The request body is larger than 10 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"415":{"description":"The `Content-Type` charset or the `Content-Encoding` is one the API cannot decode. Send UTF-8 JSON without a content encoding.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}}},"/cohorts/participants":{"get":{"operationId":"getOrganizationEmailParticipants","summary":"List all email participants","description":"Every cohort membership of the email-invited users across the whole organization, not scoped to one cohort: one row per user and cohort, removed memberships included (`state: REMOVED`). Useful for mapping users from your HR system by email address without knowing each person's cohort ahead of time.","tags":["Cohorts"],"x-required-permission":{"permission":"coaching-users:view","label":"View the list of coaching users","systemRoles":["Owner","Admin"],"link":"/roles/#coaching-users-view"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/emailParticipantResponse"}}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or your organization does not have the coaching product, or the admin's roles do not grant `coaching-users:view`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/coachingProductMissingResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}},"delete":{"operationId":"removeCoachingUsersFromOrganization","summary":"Remove users from the organization","description":"The offboarding call: deletes the given users from your Retorio organization entirely, across every cohort they belong to (both token and email users). Every id must belong to a coaching user in your organization, or the call fails as a whole and nothing is deleted. Their recordings and results are deleted with them. Inviting the same address again later restores the account rather than creating a duplicate, but not those recordings and results.","tags":["Cohorts"],"x-required-permission":{"permission":"coaching-users:manage","label":"Add, remove, disable and re-invite coaching users","systemRoles":["Owner","Admin"],"link":"/roles/#coaching-users-manage"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/userExtIdsList"}}}},"responses":{"204":{"description":"Removed"},"400":{"description":"The request body is not valid, or one or more ids are not coaching users of your organization. Nothing is deleted in that case. Also answered when the request body is not valid JSON.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or your organization does not have the coaching product, or the admin's roles do not grant `coaching-users:manage`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/coachingProductMissingResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"413":{"description":"The request body is larger than 10 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"415":{"description":"The `Content-Type` charset or the `Content-Encoding` is one the API cannot decode. Send UTF-8 JSON without a content encoding.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}}},"/cohorts/participants/resendPreview":{"get":{"operationId":"getOrganizationResendPreview","summary":"Preview a resend","description":"What an organization-wide resend would actually reach right now, broken down by cohort: only email cohorts (excluding benchmarking ones), and only the addresses currently eligible for a resend.","tags":["Cohorts"],"x-required-permission":{"permission":"coaching-users:manage","label":"Add, remove, disable and re-invite coaching users","systemRoles":["Owner","Admin"],"link":"/roles/#coaching-users-manage"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/resendPreviewResponse"}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or your organization does not have the coaching product, or the admin's roles do not grant `coaching-users:manage`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/coachingProductMissingResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}}},"/cohorts/{id}":{"get":{"operationId":"getCohort","summary":"Get a cohort","description":"One cohort of your organization, by its ext id: its name, type, creation time, whether it is used for benchmarking, and how many participants it has.","tags":["Cohorts"],"x-required-permission":{"permission":"cohorts:view","label":"View cohorts, their programs and their members","systemRoles":["Owner","Admin"],"link":"/roles/#cohorts-view"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path","example":"b2d7e4a1_55c3_4f28_9e10_7a3d6c4b8f02"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/cohortWithDetailsResponse"}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or your organization does not have the coaching product, or the admin's roles do not grant `cohorts:view`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/coachingProductMissingResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"404":{"description":"No cohort with this id in your organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}},"put":{"operationId":"updateCohort","summary":"Rename a cohort","description":"Changes the cohort’s name and nothing else: its type, participants and assigned programs stay as they are.","tags":["Cohorts"],"x-required-permission":{"permission":"cohorts:manage","label":"Create, edit and delete cohorts, and assign programs to them","systemRoles":["Owner","Admin"],"link":"/roles/#cohorts-manage"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path","example":"b2d7e4a1_55c3_4f28_9e10_7a3d6c4b8f02"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/updateCohortRequestBody"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/cohortResponse"}}}},"400":{"description":"The request body is not valid. Also answered when the request body is not valid JSON.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or your organization does not have the coaching product, or the admin's roles do not grant `cohorts:manage`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/coachingProductMissingResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"404":{"description":"No cohort with this id in your organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"413":{"description":"The request body is larger than 10 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"415":{"description":"The `Content-Type` charset or the `Content-Encoding` is one the API cannot decode. Send UTF-8 JSON without a content encoding.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}},"delete":{"operationId":"deleteCohort","summary":"Delete a cohort","description":"Deletes the cohort and its program assignments. For an `email` cohort this does not remove the users in it from your organization (use `DELETE /cohorts/participants` for that). For a `token` cohort, its token users and their tokens are deleted with it, and a token user who had signed up can no longer sign in.","tags":["Cohorts"],"x-required-permission":{"permission":"cohorts:manage","label":"Create, edit and delete cohorts, and assign programs to them","systemRoles":["Owner","Admin"],"link":"/roles/#cohorts-manage"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path","example":"b2d7e4a1_55c3_4f28_9e10_7a3d6c4b8f02"}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or your organization does not have the coaching product, or the admin's roles do not grant `cohorts:manage`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/coachingProductMissingResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"404":{"description":"No cohort with this id in your organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}}},"/cohorts/{id}/participants":{"get":{"operationId":"getCohortParticipants","summary":"List a cohort’s participants","description":"Lists the participants of one cohort. For a `token` cohort, each row carries the generated token and its status. For an `email` cohort, `token` and `status` are both null (use `emailParticipants` below for the full email-invite status instead). Add `onlyTokens` and `onlyAvailableTokens` (presence of the query param is enough, any value) to keep only tokens with status `AVAILABLE`, so not redeemed and not reserved (`onlyAvailableTokens` has no effect without `onlyTokens`), and `format=xlsx` with both of those to download that list as a spreadsheet instead of JSON.","tags":["Cohorts"],"x-required-permission":{"permission":"cohorts:view","label":"View cohorts, their programs and their members","systemRoles":["Owner","Admin"],"link":"/roles/#cohorts-view"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path","example":"b2d7e4a1_55c3_4f28_9e10_7a3d6c4b8f02"},{"schema":{"type":"string","description":"Presence flag: the filter is on whenever the key is present, whatever its value (`false` included)."},"required":false,"description":"Presence flag: the filter is on whenever the key is present, whatever its value (`false` included).","name":"onlyTokens","in":"query"},{"schema":{"type":"string","description":"Presence flag: the filter is on whenever the key is present, whatever its value (`false` included)."},"required":false,"description":"Presence flag: the filter is on whenever the key is present, whatever its value (`false` included).","name":"onlyAvailableTokens","in":"query"},{"schema":{"type":"string","description":"`xlsx`, sent together with `onlyTokens` and `onlyAvailableTokens`, returns the list as a spreadsheet instead of JSON. Ignored otherwise."},"required":false,"description":"`xlsx`, sent together with `onlyTokens` and `onlyAvailableTokens`, returns the list as a spreadsheet instead of JSON. Ignored otherwise.","name":"format","in":"query"}],"responses":{"200":{"description":"The participants as JSON. With `format=xlsx` and both token filters, an xlsx file instead (`Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`, downloaded as `tokens.xlsx`, one `Tokens` column).","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/cohortParticipantResponse"}}},"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"A query parameter is not valid, for example one sent more than once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or your organization does not have the coaching product, or the admin's roles do not grant `cohorts:view`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/coachingProductMissingResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"404":{"description":"No cohort with this id in your organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}},"delete":{"operationId":"removeCohortParticipants","summary":"Remove participants from a cohort","description":"Removes the given users from one `email` cohort, keeping their account and their membership in any other cohort. To remove a user from the organization entirely, see `DELETE /cohorts/participants` instead.","tags":["Cohorts"],"x-required-permission":{"permission":"coaching-users:manage","label":"Add, remove, disable and re-invite coaching users","systemRoles":["Owner","Admin"],"link":"/roles/#coaching-users-manage"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path","example":"b2d7e4a1_55c3_4f28_9e10_7a3d6c4b8f02"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/userExtIdsList"}}}},"responses":{"204":{"description":"Removed"},"400":{"description":"The request body is not valid, the cohort is not of type `email`, or a user does not exist or is not in it. Also answered when the request body is not valid JSON.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or your organization does not have the coaching product, or the admin's roles do not grant `coaching-users:manage`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/coachingProductMissingResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"404":{"description":"No cohort with this id in your organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"413":{"description":"The request body is larger than 10 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"415":{"description":"The `Content-Type` charset or the `Content-Encoding` is one the API cannot decode. Send UTF-8 JSON without a content encoding.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}}},"/cohorts/{id}/participants/emailParticipants":{"get":{"operationId":"getCohortEmailParticipants","summary":"List an email cohort’s invite status","description":"The cohort's email participants with their full invite lifecycle (`INVITED`, `ACTIVATED`, `DISABLED`, `REMOVED`) rather than the bare participant row `participants` above returns. One row per user, from their most recent membership in this cohort. Meant for `email` cohorts: a `token` cohort is not refused, and lists its token users the same way.","tags":["Cohorts"],"x-required-permission":{"permission":"cohorts:view","label":"View cohorts, their programs and their members","systemRoles":["Owner","Admin"],"link":"/roles/#cohorts-view"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path","example":"b2d7e4a1_55c3_4f28_9e10_7a3d6c4b8f02"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/emailParticipantResponse"}}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or your organization does not have the coaching product, or the admin's roles do not grant `cohorts:view`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/coachingProductMissingResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"404":{"description":"No cohort with this id in your organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}}},"/cohorts/{id}/participants/emails":{"post":{"operationId":"addNewEmailsToCohort","summary":"Invite users by email","description":"Adds each address to an `email`-type cohort and sends an invitation email, in one call. An address that already exists in your organization is added to this cohort rather than duplicated, and a previously deleted user is restored into this cohort. Only users who have not signed up yet are emailed, and an existing one only if they are not disabled and their last invitation is more than 24 hours old. Not idempotent: an address that is already in this cohort fails the whole call with `400`, so diff against the participant list before re-sending a batch. Invitations expire after 60 days: the coaching app then refuses to start sign-up.","tags":["Cohorts"],"x-required-permission":{"permission":"coaching-users:manage","label":"Add, remove, disable and re-invite coaching users","systemRoles":["Owner","Admin"],"link":"/roles/#coaching-users-manage"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path","example":"b2d7e4a1_55c3_4f28_9e10_7a3d6c4b8f02"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/addNewEmailsEndpoint"}}}},"responses":{"204":{"description":"Invited"},"400":{"description":"The request body is not valid, the cohort is not of type `email`, or one or more addresses are not allowed in this cohort (already in it, belongs to an admin account, or belongs to another organization). Nothing is changed in those cases. A `400` can also come after changes were made, when restoring a previously deleted user fails part-way. Also answered when the request body is not valid JSON.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or your organization does not have the coaching product, or the admin's roles do not grant `coaching-users:manage`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/coachingProductMissingResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"404":{"description":"No cohort with this id in your organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"413":{"description":"The request body is larger than 10 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"415":{"description":"The `Content-Type` charset or the `Content-Encoding` is one the API cannot decode. Send UTF-8 JSON without a content encoding.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}}},"/cohorts/{id}/participants/resendEmails":{"post":{"operationId":"resendCohortEmailInvitations","summary":"Resend invitation emails","description":"Re-sends the invitation email in an `email` cohort, in one of two ways. Send `{ \"userExtIds\": [...] }` to name specific not-yet-registered recipients yourself: this is all-or-nothing, so one ineligible id refuses the whole request before anything is sent, and a successful call returns `204` with no body. Send `{ \"select\": \"next\" }` instead to let Retorio pick whoever is next eligible and send to them. That form returns `200` with how many were just sent and how many eligible recipients remain, so you can call it again to work through a large cohort in batches. Both forms reach only users whose last invitation is more than 24 hours old. A user with no recorded invitation is not eligible. Disabled users are never eligible. Each `{ \"select\": \"next\" }` call sends at most 20.","tags":["Cohorts"],"x-required-permission":{"permission":"coaching-users:manage","label":"Add, remove, disable and re-invite coaching users","systemRoles":["Owner","Admin"],"link":"/roles/#coaching-users-manage"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path","example":"b2d7e4a1_55c3_4f28_9e10_7a3d6c4b8f02"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"userExtIds":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":200,"description":"List of user ext ids","example":["6f1c0a2e_9b41_4d0c_8a7e_2f5b8c1d0e93"]}},"required":["userExtIds"],"additionalProperties":false},{"type":"object","properties":{"select":{"type":"string","enum":["next"]}},"required":["select"],"additionalProperties":false}]}}}},"responses":{"200":{"description":"Sent the next eligible batch (the `{ \"select\": \"next\" }` form only).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/resendEmailsBatchResponse"}}}},"204":{"description":"Resent (the `userExtIds` form only)."},"400":{"description":"The request body is not valid, the cohort is not of type `email`, or (`userExtIds` form only) a named user does not exist or is not eligible. Also answered when the request body is not valid JSON.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or your organization does not have the coaching product, or the admin's roles do not grant `coaching-users:manage`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/coachingProductMissingResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"404":{"description":"No cohort with this id in your organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"413":{"description":"The request body is larger than 10 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"415":{"description":"The `Content-Type` charset or the `Content-Encoding` is one the API cannot decode. Send UTF-8 JSON without a content encoding.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}}},"/cohorts/{id}/participants/tokens":{"post":{"operationId":"addCohortTokens","summary":"Generate tokens","description":"Generates new access tokens for a `token`-type cohort, to hand to coaching users directly instead of inviting them by email: through your own LMS, HR system, or in person. The response has no body: fetch the generated tokens with `GET /cohorts/{id}/participants` right after. A token is meant to be redeemed once and does not expire on its own. Redeeming it replaces the token value, so the participant list then shows a different token for that user than the one handed out. Match on `userId`, not on the token. Each token has its own user (`userId` in the participant list). Removing that user with `DELETE /cohorts/participants` revokes the token.","tags":["Cohorts"],"x-required-permission":{"permission":"coaching-users:manage","label":"Add, remove, disable and re-invite coaching users","systemRoles":["Owner","Admin"],"link":"/roles/#coaching-users-manage"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path","example":"b2d7e4a1_55c3_4f28_9e10_7a3d6c4b8f02"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/addCohortTokensRequestBody"}}}},"responses":{"204":{"description":"Generated"},"400":{"description":"The request body is not valid, or the cohort is not of type `token`. Also answered when the request body is not valid JSON.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or your organization does not have the coaching product, or the admin's roles do not grant `coaching-users:manage`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/coachingProductMissingResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"404":{"description":"No cohort with this id in your organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"413":{"description":"The request body is larger than 10 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"415":{"description":"The `Content-Type` charset or the `Content-Encoding` is one the API cannot decode. Send UTF-8 JSON without a content encoding.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}}},"/cohorts/{id}/participants/{userExtId}/updateUserActivationStatus":{"put":{"operationId":"updateCohortParticipantActivationStatus","summary":"Enable or disable a participant","description":"Enables or disables a user, addressed through an `email` cohort. The flag belongs to the user, so it applies across every cohort they are in. The coaching app does not let a disabled user who has not signed up yet start sign-up. One who already has can still sign in, but none of their programs can be started. Re-enabling a user who never registered sends them a fresh invitation email, subject to the same 24-hour throttle as `POST /cohorts/{id}/participants/emails`.","tags":["Cohorts"],"x-required-permission":{"permission":"coaching-users:manage","label":"Add, remove, disable and re-invite coaching users","systemRoles":["Owner","Admin"],"link":"/roles/#coaching-users-manage"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path","example":"b2d7e4a1_55c3_4f28_9e10_7a3d6c4b8f02"},{"schema":{"type":"string"},"required":true,"name":"userExtId","in":"path","example":"6f1c0a2e_9b41_4d0c_8a7e_2f5b8c1d0e93"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/updateUserStatusEndpoint"}}}},"responses":{"204":{"description":"Updated"},"400":{"description":"The request body is not valid, or the cohort is not of type `email`. Also answered when the request body is not valid JSON.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or your organization does not have the coaching product, or the admin's roles do not grant `coaching-users:manage`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/coachingProductMissingResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"404":{"description":"No cohort with this id in your organization, or this user has never been a participant of it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"413":{"description":"The request body is larger than 10 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"415":{"description":"The `Content-Type` charset or the `Content-Encoding` is one the API cannot decode. Send UTF-8 JSON without a content encoding.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}}},"/cohorts/{id}/programs":{"get":{"operationId":"getCohortPrograms","summary":"List a cohort’s assigned programs","description":"Lists the programs assigned to this cohort, with each assignment’s window, status and per-scenario publish counts, ordered the way the admin app shows them.","tags":["Cohorts"],"x-required-permission":{"permission":"cohorts:view","label":"View cohorts, their programs and their members","systemRoles":["Owner","Admin"],"link":"/roles/#cohorts-view"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path","example":"b2d7e4a1_55c3_4f28_9e10_7a3d6c4b8f02"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/cohortProgramResponse"}}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or your organization does not have the coaching product, or the admin's roles do not grant `cohorts:view`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/coachingProductMissingResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"404":{"description":"No cohort with this id in your organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}},"post":{"operationId":"createCohortPrograms","summary":"Assign programs to a cohort","description":"Assigns one or more programs to this cohort for the given window. Fails the whole call if any of the programs already holds a live assignment in this cohort.","tags":["Cohorts"],"x-required-permission":{"permission":"cohorts:manage","label":"Create, edit and delete cohorts, and assign programs to them","systemRoles":["Owner","Admin"],"link":"/roles/#cohorts-manage"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path","example":"b2d7e4a1_55c3_4f28_9e10_7a3d6c4b8f02"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/createCohortProgramsRequestBody"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/cohortProgramResponse"}}}}},"400":{"description":"The request body is not valid, a date is not a valid ISO date, `startDate` is not before `endDate`, or a program already holds a live assignment in this cohort. Also answered when the request body is not valid JSON.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or your organization does not have the coaching product, or the admin's roles do not grant `cohorts:manage`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/coachingProductMissingResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"404":{"description":"No cohort with this id in your organization, or a program in `programExtIds` does not exist in it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"413":{"description":"The request body is larger than 10 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"415":{"description":"The `Content-Type` charset or the `Content-Encoding` is one the API cannot decode. Send UTF-8 JSON without a content encoding.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}}},"/cohorts/{id}/programs/order":{"post":{"operationId":"updateCohortProgramsOrder","summary":"Reorder a cohort’s assigned programs","description":"Sets the display order of this cohort’s assignments. Send exactly one entry per assignment, with `order` values covering `0` to `n - 1`. An unknown or repeated ext id, a different number of entries than assignments, or `order` values that are not exactly `0` to `n - 1` (a gap or a repeat) fails the whole call.","tags":["Cohorts"],"x-required-permission":{"permission":"cohorts:manage","label":"Create, edit and delete cohorts, and assign programs to them","systemRoles":["Owner","Admin"],"link":"/roles/#cohorts-manage"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path","example":"b2d7e4a1_55c3_4f28_9e10_7a3d6c4b8f02"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/updateCohortProgramsOrderRequestBody"}}}},"responses":{"204":{"description":"Updated"},"400":{"description":"The request body is not valid, an ext id is not one of this cohort's assignments, the number of entries differs from the number of assignments, or the `order` values are not exactly `0` to `n - 1`. Also answered when the request body is not valid JSON.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or your organization does not have the coaching product, or the admin's roles do not grant `cohorts:manage`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/coachingProductMissingResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"404":{"description":"No cohort with this id in your organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"413":{"description":"The request body is larger than 10 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"415":{"description":"The `Content-Type` charset or the `Content-Encoding` is one the API cannot decode. Send UTF-8 JSON without a content encoding.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}}},"/cohorts/{id}/programs/unused":{"get":{"operationId":"getUnusedCohortPrograms","summary":"List programs not yet assigned to a cohort","description":"Lists the organization’s programs holding no assignment in this cohort: the picker for `POST /cohorts/{id}/programs`. A program whose assignment here has ended does not appear: an ended assignment is edited, not repeated.","tags":["Cohorts"],"x-required-permission":{"permission":"cohorts:manage","label":"Create, edit and delete cohorts, and assign programs to them","systemRoles":["Owner","Admin"],"link":"/roles/#cohorts-manage"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path","example":"b2d7e4a1_55c3_4f28_9e10_7a3d6c4b8f02"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/unusedCohortProgramResponse"}}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or your organization does not have the coaching product, or the admin's roles do not grant `cohorts:manage`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/coachingProductMissingResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"404":{"description":"No cohort with this id in your organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}}},"/cohorts/{id}/programs/{cohortProgramExtId}":{"get":{"operationId":"getCohortProgram","summary":"Get one cohort-program assignment","description":"One program assigned to the cohort: the program, its period and position, whether it is upcoming, active or finished, and its scenarios counted by publish status.","tags":["Cohorts"],"x-required-permission":{"permission":"cohorts:view","label":"View cohorts, their programs and their members","systemRoles":["Owner","Admin"],"link":"/roles/#cohorts-view"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path","example":"b2d7e4a1_55c3_4f28_9e10_7a3d6c4b8f02"},{"schema":{"type":"string"},"required":true,"name":"cohortProgramExtId","in":"path","example":"e90f3b7c_1a26_44d5_b8c1_0d94e7f25a63"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/cohortProgramResponse"}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or your organization does not have the coaching product, or the admin's roles do not grant `cohorts:view`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/coachingProductMissingResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"404":{"description":"No cohort with this id in your organization, or no assignment with this ext id in it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}},"put":{"operationId":"updateCohortProgram","summary":"Change an assignment’s window","description":"Changes the `startDate`/`endDate` of an existing assignment.","tags":["Cohorts"],"x-required-permission":{"permission":"cohorts:manage","label":"Create, edit and delete cohorts, and assign programs to them","systemRoles":["Owner","Admin"],"link":"/roles/#cohorts-manage"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path","example":"b2d7e4a1_55c3_4f28_9e10_7a3d6c4b8f02"},{"schema":{"type":"string"},"required":true,"name":"cohortProgramExtId","in":"path","example":"e90f3b7c_1a26_44d5_b8c1_0d94e7f25a63"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/updateCohortProgramRequestBody"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/cohortProgramResponse"}}}},"400":{"description":"The request body is not valid, a date is not a valid ISO date, or `startDate` is not before `endDate`. Also answered when the request body is not valid JSON.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or your organization does not have the coaching product, or the admin's roles do not grant `cohorts:manage`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/coachingProductMissingResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"404":{"description":"No cohort with this id in your organization, or no assignment with this ext id in it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"413":{"description":"The request body is larger than 10 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"415":{"description":"The `Content-Type` charset or the `Content-Encoding` is one the API cannot decode. Send UTF-8 JSON without a content encoding.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}},"delete":{"operationId":"deleteCohortProgram","summary":"Unassign a program from a cohort","description":"Removes the assignment and compacts the remaining assignments’ `order` values. The program itself, and any data already recorded under it, is unaffected.","tags":["Cohorts"],"x-required-permission":{"permission":"cohorts:manage","label":"Create, edit and delete cohorts, and assign programs to them","systemRoles":["Owner","Admin"],"link":"/roles/#cohorts-manage"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path","example":"b2d7e4a1_55c3_4f28_9e10_7a3d6c4b8f02"},{"schema":{"type":"string"},"required":true,"name":"cohortProgramExtId","in":"path","example":"e90f3b7c_1a26_44d5_b8c1_0d94e7f25a63"}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or your organization does not have the coaching product, or the admin's roles do not grant `cohorts:manage`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/coachingProductMissingResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"404":{"description":"No cohort with this id in your organization, or no assignment with this ext id in it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}}},"/organization_webhooks":{"get":{"operationId":"getOrganizationWebhooks","summary":"List webhooks","description":"Lists the webhooks configured for your organization, up to the limit of 5. No secret value is returned here: custom headers are listed by *name* only, and the signing secret is returned only by create and by an update that rotates it.","tags":["Webhooks"],"x-required-permission":{"permission":"webhooks:manage","label":"Create, edit and delete webhooks, and view their deliveries","systemRoles":["Owner"],"link":"/roles/#webhooks-manage"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/getOrganizationWebhooksResponse"}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or the admin's roles do not grant `webhooks:manage`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}},"post":{"operationId":"createOrganizationWebhook","summary":"Create a webhook","description":"Creates a webhook and its first configuration version. The response includes the `signingSecret` in plaintext (returned only here and by an update that rotates it), so store it immediately: it is required to verify the `X-Retorio-Signature` header on every delivery. An organization may have at most 5 webhooks, disabled ones included.","tags":["Webhooks"],"callbacks":{"coaching.result.available":{"{$request.body#/url}":{"post":{"security":[],"summary":"A subscribed event is delivered to your endpoint","description":"Retorio sends this request to the URL you configured, signed with your webhook's `signingSecret`. A receiver needs four of the request headers below: `X-Retorio-Signature` and `X-Retorio-Timestamp` to verify the request, `X-Retorio-Delivery-Id` to deduplicate it and `X-Retorio-Event-Type` to route it. The others identify the sender or the trace. Your custom headers are sent too, except one whose name matches an `X-Retorio-` header, `Content-Type` or `User-Agent`. Delivery is at-least-once: deduplicate on `X-Retorio-Delivery-Id`. A coaching result is first sent at least five and a half minutes after it is ready, at the next delivery run after that delay, so that its session times are final.","parameters":[{"name":"X-Retorio-Signature","in":"header","required":true,"description":"`v1,<base64 HMAC-SHA256>` of `<X-Retorio-Timestamp>.<raw body>`, keyed with the webhook's signing secret. The HMAC key is the full `signingSecret` string exactly as returned, `whsec_` prefix included, taken as UTF-8 bytes. Do not strip the prefix or base64-decode it.","schema":{"type":"string"}},{"name":"X-Retorio-Timestamp","in":"header","required":true,"description":"Unix time in seconds at which this attempt was signed.","schema":{"type":"string"}},{"name":"X-Retorio-Delivery-Id","in":"header","required":true,"description":"Stable across retries of the same event. Deduplicate on it.","schema":{"type":"string"}},{"name":"X-Retorio-Event-Type","in":"header","required":true,"description":"The event type, the same as `eventType` in the body.","schema":{"type":"string"}},{"name":"Content-Type","in":"header","required":true,"description":"Always `application/json`.","schema":{"type":"string"}},{"name":"User-Agent","in":"header","required":true,"description":"`Retorio-Webhooks/<version>`, the Retorio version that sent it.","schema":{"type":"string"}},{"name":"X-Retorio-Api-Env","in":"header","required":true,"description":"The Retorio environment that sent the request, for example `prod` or `staging`.","schema":{"type":"string"}},{"name":"X-Retorio-Api-Version","in":"header","required":true,"description":"The Retorio version that sent the request.","schema":{"type":"string"}},{"name":"X-Retorio-Api-Deployment","in":"header","required":true,"description":"The Retorio deployment that sent the request. Together with the environment, it tells deliveries from different Retorio systems apart on one endpoint.","schema":{"type":"string"}},{"name":"traceparent","in":"header","required":false,"description":"Usually present. A standard W3C trace ID that lets Retorio find this delivery in its logs, so include it when you report a problem. Your endpoint can ignore it.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhookEventEnvelope"}}}},"responses":{"2XX":{"description":"Any 2xx response acknowledges the delivery. The response body does not affect the outcome. Requests time out after 10 seconds. A timeout, no response, a 5xx, a 408 or a 429 is retried with backoff for roughly a day. Any other 4xx, and any 3xx (redirects are not followed), is treated as a refusal and is not retried."}}}}}},"x-required-permission":{"permission":"webhooks:manage","label":"Create, edit and delete webhooks, and view their deliveries","systemRoles":["Owner"],"link":"/roles/#webhooks-manage"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/createOrganizationWebhookRequestBody"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/organizationWebhookWithSecretResponse"}}}},"400":{"description":"The configuration is not valid (see the request fields), a custom header entry without a `value` names no stored header or the stored headers cannot be read, the custom headers exceed 8192 bytes once merged, your organization already has 5 webhooks (create only), or this environment cannot store webhook credentials. Also answered when the request body is not valid JSON.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or the admin's roles do not grant `webhooks:manage`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"413":{"description":"The request body is larger than 10 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"415":{"description":"The `Content-Type` charset or the `Content-Encoding` is one the API cannot decode. Send UTF-8 JSON without a content encoding.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}}},"/organization_webhooks/{extId}":{"put":{"operationId":"updateOrganizationWebhook","summary":"Update a webhook","description":"Updates a webhook by appending a new configuration version. The full configuration is restated on every update, not patched: `customHeaders` omitted keeps the stored set (credential included), `[]` removes every custom header, and an array that is sent is the whole set going forward. Inside a sent array, an entry with a `name` and no `value` keeps the value stored under that name, so you can keep a credential you cannot read back. An entry with no `value` whose name is not stored is a `400`. Pass `expectedLastChangedAt` (the `lastChangedAt` you last read) to get a `409` instead of overwriting an edit made since you read it. A `409` can also answer an update that collides with a concurrent one. `rotateSigningSecret: true` replaces the signing secret and returns the new one once. Every receiver verifying with the old one then fails until updated.","tags":["Webhooks"],"x-required-permission":{"permission":"webhooks:manage","label":"Create, edit and delete webhooks, and view their deliveries","systemRoles":["Owner"],"link":"/roles/#webhooks-manage"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"extId","in":"path","example":"9d4e2b71_3c8a_4f05_b6e2_1a7c5d9e0f38"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/updateOrganizationWebhookRequestBody"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/organizationWebhookWithSecretResponse"}}}},"400":{"description":"The configuration is not valid (see the request fields), a custom header entry without a `value` names no stored header or the stored headers cannot be read, the custom headers exceed 8192 bytes once merged, your organization already has 5 webhooks (create only), or this environment cannot store webhook credentials. Also answered when the request body is not valid JSON.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or the admin's roles do not grant `webhooks:manage`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"404":{"description":"No webhook with this extId in your organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"409":{"description":"The webhook was edited by someone else since `expectedLastChangedAt`, or by a concurrent update that committed first. Reload it and retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"413":{"description":"The request body is larger than 10 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"415":{"description":"The `Content-Type` charset or the `Content-Encoding` is one the API cannot decode. Send UTF-8 JSON without a content encoding.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/httpExceptionResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}},"delete":{"operationId":"deleteOrganizationWebhook","summary":"Delete a webhook","description":"Soft-deletes a webhook and every configuration version it has had. No further retries are sent: each pending delivery is cancelled when it next comes due, and only a request already on its way at the moment of deletion can still arrive. Its delivery records are retained but no longer readable through this API: `GET /organization_webhooks/{extId}/deliveries` answers `404` once the webhook is deleted.","tags":["Webhooks"],"x-required-permission":{"permission":"webhooks:manage","label":"Create, edit and delete webhooks, and view their deliveries","systemRoles":["Owner"],"link":"/roles/#webhooks-manage"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"extId","in":"path","example":"9d4e2b71_3c8a_4f05_b6e2_1a7c5d9e0f38"}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or the admin's roles do not grant `webhooks:manage`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"404":{"description":"No webhook with this extId in your organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}}},"/organization_webhooks/{extId}/deliveries":{"get":{"operationId":"getOrganizationWebhookDeliveries","summary":"List recent deliveries","description":"The webhook's most recent deliveries (up to 50), newest first, across every configuration version it has ever had. One row per event, summarizing its attempts (`attemptCount`, `lastStatusCode`, `lastError`), useful for diagnosing a receiver that is failing or has gone quiet. `lastError` holds at most 500 characters. On a `cancelled` row, and on a `failed` row Retorio settled without recording a send (a delivery Retorio stopped retrying for its own reasons, a stored event that no longer validates, a test whose outcome could not be recorded), it holds Retorio's reason, which replaces the last error text, while `lastStatusCode` keeps the code of the last recorded attempt. `updatedAt` is the creation time and does not track status changes: read `status` and `deliveredAt` instead.","tags":["Webhooks"],"x-required-permission":{"permission":"webhooks:manage","label":"Create, edit and delete webhooks, and view their deliveries","systemRoles":["Owner"],"link":"/roles/#webhooks-manage"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"extId","in":"path","example":"9d4e2b71_3c8a_4f05_b6e2_1a7c5d9e0f38"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/getOrganizationWebhookDeliveriesResponse"}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or the admin's roles do not grant `webhooks:manage`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"404":{"description":"No webhook with this extId in your organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}}},"/organization_webhooks/{extId}/test":{"post":{"operationId":"testOrganizationWebhook","summary":"Send a test event","description":"Sends a synchronous `webhook.test` event to the webhook, signed exactly like a real delivery, so you can verify your receiver end to end. Sent even when the webhook is disabled, so you can create it with `isEnabled: false`, test it, then enable it: a webhook created enabled receives its subscribed events right away. Recorded as a delivery, so it also shows up in the delivery log. It is never retried.","tags":["Webhooks"],"x-required-permission":{"permission":"webhooks:manage","label":"Create, edit and delete webhooks, and view their deliveries","systemRoles":["Owner"],"link":"/roles/#webhooks-manage"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"extId","in":"path","example":"9d4e2b71_3c8a_4f05_b6e2_1a7c5d9e0f38"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/testOrganizationWebhookResponse"}}}},"401":{"description":"Not authenticated: the bearer token is missing, malformed, expired or revoked, its sign-in method does not match your organization's configuration, the user it belongs to was removed, or your organization is deactivated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"403":{"description":"Refused: the token does not belong to an admin, or the admin's roles do not grant `webhooks:manage`.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/appErrorResponse"},{"$ref":"#/components/schemas/httpExceptionResponse"}]}}}},"404":{"description":"No webhook with this extId in your organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/appErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"nullable":true}}}}}}}}},"servers":[{"url":"https://api.retorio.com/be/v2"}]}