generated: '2026-08-12' method: derived source: openapi/adready-cpxi-kickstart-openapi.yml + live unauthenticated probes of https://platform.digitalremedy.com note: >- The published OpenAPI declares NO components.securitySchemes and NO top-level or per-operation security[] requirements, so nothing here is derived from a declared scheme. The auth model below is reconstructed from the authentication and token operations the spec DOES describe, corroborated by live unauthenticated probes: every business path returns HTTP 401 with an empty body, while /version, /health-check, /api/version, /api/theme and /api/config answer 200 anonymously. This gap between the deployed enforcement and the described contract is the finding — an agent reading this spec alone cannot tell that the API requires authentication, or how to obtain a token. summary: types: - session-jwt api_key_in: [] oauth2_flows: [] declared_in_spec: false enforced_at_runtime: true schemes: - name: SessionJWT type: http scheme: bearer bearer_format: JWT declared_in_openapi: false status: undeclared-but-enforced description: >- A session JSON Web Token issued by POST /api/auth/login and managed by the token-controller operations. The spec does not describe where the credential is carried (header vs cookie); the login response is typed only as a bare object, and the browser client sets axios withCredentials true, which is consistent with a cookie-borne session. Confirming the exact carrier requires an authenticated session and was not attempted. sources: - openapi/adready-cpxi-kickstart-openapi.yml credential_operations: - operationId: authenticateUser method: post path: /api/auth/login purpose: Exchange email + password for a session token request_schema: LoginRequest request_fields: - email (string, format email, required) - password (string, required) query_parameters: - name: app required: true type: integer note: Application discriminator; the spec documents no enumeration of valid values. - operationId: authenticatePlusUser method: post path: /api/auth/plus_login purpose: Login path for the legacy AdReady+ (plus.adready.com) application - operationId: loginAhUser method: post path: /api/auth/loginC360User purpose: Login path for Compulse 360 (C360) users, following the Compulse / Digital Remedy combination - operationId: refreshToken method: get path: /api/token/refresh purpose: Refresh the session token response_schema: ApiResponseTokenWrapper - operationId: parseJwtToken method: get path: /api/token/parse purpose: Parse and inspect the current JWT - operationId: removeJwtToken method: delete path: /api/token/remove purpose: Invalidate the session token (logout) password_lifecycle_operations: - {operationId: createPassword, method: post, path: /api/auth/forgot_password} - {operationId: createPassword_1, method: post, path: /api/auth/create_password} - {operationId: ResetPassword, method: post, path: /api/auth/reset_password} - {operationId: validateResetPasswordToken, method: post, path: /api/auth/validate_token} - {operationId: sendVerificationEmail, method: post, path: /api/sendVerificationEmail} delegated_analytics_tokens: note: >- The API mints short-lived tokens for embedded third-party analytics surfaces rather than exposing those systems directly. These are outbound delegation, not inbound API authentication. operations: - {operationId: tableauJwtToken, path: '/api/token/tableau', target: Tableau} - {operationId: tableauJwtTokenByAccount, path: '/api/token/tableau/account/{accountId}', target: Tableau} - {operationId: tableauJwtToken_1, path: '/api/token/tableau/{advertiserId}', target: Tableau} - {operationId: tableauSignInTokenByAdvertiser, path: '/api/token/tableau/sign/{advertiserId}', target: Tableau} - {operationId: generateThoughtSpotToken, path: '/api/token/thoughtSpot', target: ThoughtSpot} anonymous_operations: note: Observed 200 without credentials on 2026-08-12. paths: - {path: /version, status: 200, returns: build metadata (version, git revision, build time)} - {path: /api/version, status: 200, returns: build metadata} - {path: /health-check, status: 200, returns: 'plain text: server is up'} - {path: /api/theme, status: 200, returns: white-label theme CSS} - {path: /api/config, status: 200, returns: client bootstrap configuration} - {path: /v3/api-docs, status: 200, returns: the OpenAPI 3.1 description itself} - {path: /swagger-ui.html, status: 200, returns: Swagger UI} runtime_evidence: - {url: 'https://platform.digitalremedy.com/api/users/1', status: 401, body_length: 0, www_authenticate: absent} - {url: 'https://platform.digitalremedy.com/config', status: 401, body_length: 0} - {url: 'https://platform.digitalremedy.com/version', status: 200} - {url: 'https://platform.digitalremedy.com/v3/api-docs', status: 200} gaps: - No securitySchemes declared in the OpenAPI, so no operation states its auth requirement. - The 401 response carries no body and no WWW-Authenticate challenge header. - Only one operation in 355 documents a 401 response and only one documents a 403. - No OAuth 2.0, no OpenID Connect, no API keys, and therefore no scope surface. - No public sign-up: credentials are provisioned by Digital Remedy, not self-served.